@gearbox-protocol/sdk 14.12.0-next.1 → 14.12.0-next.3

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 (91) hide show
  1. package/dist/cjs/abi/iZapper.js +62 -24
  2. package/dist/cjs/preview/parse/errors.js +5 -2
  3. package/dist/cjs/preview/parse/index.js +2 -0
  4. package/dist/cjs/preview/parse/parseOperationCalldata.js +38 -1
  5. package/dist/cjs/preview/parse/parsePoolOperationCalldata.js +10 -2
  6. package/dist/cjs/preview/parse/parseRWAFactoryOperationCalldata.js +92 -0
  7. package/dist/cjs/preview/prerequisites/buildPrerequisites.js +57 -10
  8. package/dist/cjs/preview/simulate/errors.js +0 -7
  9. package/dist/cjs/preview/simulate/index.js +0 -3
  10. package/dist/cjs/preview/simulate/simulatePoolOperation.js +154 -29
  11. package/dist/cjs/sdk/MultichainSDK.js +1 -0
  12. package/dist/cjs/sdk/OnchainSDK.js +7 -3
  13. package/dist/cjs/sdk/market/MarketRegister.js +10 -5
  14. package/dist/cjs/sdk/market/ZapperRegister.js +54 -0
  15. package/dist/cjs/sdk/market/rwa/securitize/SecuritizeRWAFactory.js +20 -0
  16. package/dist/cjs/sdk/market/zapper/IERC20ZapperContract.js +3 -38
  17. package/dist/cjs/sdk/market/zapper/IETHZapperContract.js +3 -38
  18. package/dist/cjs/sdk/market/zapper/ZapperContract.js +109 -0
  19. package/dist/cjs/sdk/market/zapper/createZapper.js +12 -4
  20. package/dist/cjs/{preview/simulate/constants.js → sdk/market/zapper/errors.js} +15 -6
  21. package/dist/cjs/sdk/market/zapper/index.js +6 -2
  22. package/dist/cjs/sdk/market/zapper/types.js +16 -0
  23. package/dist/cjs/sdk/options.js +41 -17
  24. package/dist/esm/abi/iZapper.js +62 -24
  25. package/dist/esm/preview/parse/errors.js +3 -1
  26. package/dist/esm/preview/parse/index.js +1 -0
  27. package/dist/esm/preview/parse/parseOperationCalldata.js +41 -2
  28. package/dist/esm/preview/parse/parsePoolOperationCalldata.js +10 -2
  29. package/dist/esm/preview/parse/parseRWAFactoryOperationCalldata.js +71 -0
  30. package/dist/esm/preview/prerequisites/buildPrerequisites.js +57 -10
  31. package/dist/esm/preview/simulate/errors.js +0 -6
  32. package/dist/esm/preview/simulate/index.js +0 -2
  33. package/dist/esm/preview/simulate/simulatePoolOperation.js +155 -30
  34. package/dist/esm/sdk/MultichainSDK.js +1 -0
  35. package/dist/esm/sdk/OnchainSDK.js +7 -3
  36. package/dist/esm/sdk/market/MarketRegister.js +10 -5
  37. package/dist/esm/sdk/market/ZapperRegister.js +54 -0
  38. package/dist/esm/sdk/market/rwa/securitize/SecuritizeRWAFactory.js +23 -1
  39. package/dist/esm/sdk/market/zapper/IERC20ZapperContract.js +3 -38
  40. package/dist/esm/sdk/market/zapper/IETHZapperContract.js +3 -38
  41. package/dist/esm/sdk/market/zapper/ZapperContract.js +85 -0
  42. package/dist/esm/sdk/market/zapper/createZapper.js +12 -4
  43. package/dist/esm/sdk/market/zapper/errors.js +13 -0
  44. package/dist/esm/sdk/market/zapper/index.js +3 -1
  45. package/dist/esm/sdk/market/zapper/types.js +0 -0
  46. package/dist/esm/sdk/options.js +39 -15
  47. package/dist/types/abi/iERC20Zapper.d.ts +91 -23
  48. package/dist/types/abi/iETHZapper.d.ts +91 -23
  49. package/dist/types/abi/iZapper.d.ts +91 -23
  50. package/dist/types/preview/parse/classifyInnerOperations.d.ts +0 -2
  51. package/dist/types/preview/parse/errors.d.ts +1 -0
  52. package/dist/types/preview/parse/index.d.ts +1 -0
  53. package/dist/types/preview/parse/parseOperationCalldata.d.ts +3 -3
  54. package/dist/types/preview/parse/parseRWAFactoryOperationCalldata.d.ts +23 -0
  55. package/dist/types/preview/parse/types-pools.d.ts +61 -1
  56. package/dist/types/preview/prerequisites/buildPrerequisites.d.ts +1 -1
  57. package/dist/types/preview/simulate/errors.d.ts +6 -12
  58. package/dist/types/preview/simulate/index.d.ts +0 -1
  59. package/dist/types/preview/simulate/simulatePoolOperation.d.ts +22 -4
  60. package/dist/types/preview/simulate/types.d.ts +3 -16
  61. package/dist/types/sdk/MultichainSDK.d.ts +5 -0
  62. package/dist/types/sdk/OnchainSDK.d.ts +4 -0
  63. package/dist/types/sdk/market/MarketRegister.d.ts +15 -6
  64. package/dist/types/sdk/market/ZapperRegister.d.ts +25 -4
  65. package/dist/types/sdk/market/rwa/securitize/SecuritizeRWAFactory.d.ts +2 -1
  66. package/dist/types/sdk/market/zapper/IERC20ZapperContract.d.ts +93 -39
  67. package/dist/types/sdk/market/zapper/IETHZapperContract.d.ts +93 -39
  68. package/dist/types/sdk/market/zapper/ZapperContract.d.ts +35 -0
  69. package/dist/types/sdk/market/zapper/createZapper.d.ts +2 -4
  70. package/dist/types/sdk/market/zapper/errors.d.ts +10 -0
  71. package/dist/types/sdk/market/zapper/index.d.ts +3 -1
  72. package/dist/types/sdk/market/zapper/types.d.ts +64 -0
  73. package/dist/types/sdk/options.d.ts +10 -5
  74. package/dist/types/sdk/pools/types.d.ts +3 -3
  75. package/dist/types/sdk/types/state-human.d.ts +9 -0
  76. package/dist/types/sdk/types/state.d.ts +7 -0
  77. package/package.json +3 -3
  78. package/dist/cjs/preview/simulate/extractERC20Transfers.js +0 -47
  79. package/dist/cjs/preview/simulate/simulatePoolOpMulticall.js +0 -155
  80. package/dist/cjs/preview/simulate/simulatePoolOpV1.js +0 -106
  81. package/dist/cjs/sdk/market/zapper/Zapper.js +0 -47
  82. package/dist/esm/preview/simulate/constants.js +0 -4
  83. package/dist/esm/preview/simulate/extractERC20Transfers.js +0 -23
  84. package/dist/esm/preview/simulate/simulatePoolOpMulticall.js +0 -130
  85. package/dist/esm/preview/simulate/simulatePoolOpV1.js +0 -82
  86. package/dist/esm/sdk/market/zapper/Zapper.js +0 -23
  87. package/dist/types/preview/simulate/constants.d.ts +0 -6
  88. package/dist/types/preview/simulate/extractERC20Transfers.d.ts +0 -11
  89. package/dist/types/preview/simulate/simulatePoolOpMulticall.d.ts +0 -28
  90. package/dist/types/preview/simulate/simulatePoolOpV1.d.ts +0 -14
  91. package/dist/types/sdk/market/zapper/Zapper.d.ts +0 -13
@@ -1,41 +1,166 @@
1
- import { ETH_SIMULATE_V1_NETWORKS } from "./constants.js";
1
+ import { iPoolV310Abi } from "../../abi/310/generated.js";
2
+ import { ierc20Abi } from "../../abi/iERC20.js";
3
+ import { iZapperAbi } from "../../abi/iZapper.js";
4
+ import { AddressMap } from "../../sdk/index.js";
2
5
  import {
3
6
  asPreviewSimulationError,
4
- combinePreviewSimulationErrors
7
+ decodeSimulationError,
8
+ PreviewSimulationError
5
9
  } from "./errors.js";
6
- import { simulatePoolOpMulticall } from "./simulatePoolOpMulticall.js";
7
- import { simulatePoolOpV1 } from "./simulatePoolOpV1.js";
10
+ import { watchedHolders } from "./holders.js";
11
+ function previewRead(operation) {
12
+ switch (operation.operation) {
13
+ case "Deposit":
14
+ return { functionName: "previewDeposit", amount: operation.assets };
15
+ case "Mint":
16
+ return { functionName: "previewMint", amount: operation.shares };
17
+ case "Withdraw":
18
+ return { functionName: "previewWithdraw", amount: operation.assets };
19
+ case "Redeem":
20
+ return { functionName: "previewRedeem", amount: operation.shares };
21
+ }
22
+ }
23
+ function outsideToken(operation) {
24
+ switch (operation.operation) {
25
+ case "Deposit":
26
+ case "Mint":
27
+ return operation.tokenIn;
28
+ case "Withdraw":
29
+ case "Redeem":
30
+ return operation.tokenOut;
31
+ }
32
+ }
33
+ function previewContract(operation) {
34
+ const { functionName, amount } = previewRead(operation);
35
+ if (operation.zapper) {
36
+ return {
37
+ address: operation.zapper,
38
+ abi: iZapperAbi,
39
+ functionName,
40
+ args: [amount]
41
+ };
42
+ }
43
+ return {
44
+ address: operation.pool,
45
+ abi: iPoolV310Abi,
46
+ functionName,
47
+ args: [amount]
48
+ };
49
+ }
8
50
  async function simulatePoolOperation(input, options = {}) {
9
- const { sdk } = input;
10
- const { logger } = options;
11
- const useSimulateV1 = options.useSimulateV1 ?? ETH_SIMULATE_V1_NETWORKS.has(sdk.networkType);
12
- logger?.debug(
13
- { wallet: input.wallet, to: input.to },
14
- "simulating pool operation"
15
- );
16
- const [v1, multicall] = await Promise.allSettled([
17
- useSimulateV1 ? simulatePoolOpV1(input, options) : void 0,
18
- simulatePoolOpMulticall(input, options)
19
- ]);
20
- if (v1.status === "fulfilled" && v1.value) {
21
- return { status: "success", ...v1.value };
51
+ const { sdk, operation, wallet } = input;
52
+ const { blockNumber, logger } = options;
53
+ const { pool } = operation;
54
+ try {
55
+ const holders = watchedHolders(operation, wallet);
56
+ const tokens = [outsideToken(operation), pool];
57
+ const balanceCalls = holders.flatMap(
58
+ (holder) => tokens.map((token) => ({ holder, token }))
59
+ );
60
+ const balanceContracts = balanceCalls.map(
61
+ ({ holder, token }) => ({
62
+ address: token,
63
+ abi: ierc20Abi,
64
+ functionName: "balanceOf",
65
+ args: [holder]
66
+ })
67
+ );
68
+ const preview = previewContract(operation);
69
+ let results;
70
+ try {
71
+ results = await sdk.client.multicall({
72
+ allowFailure: false,
73
+ // `undefined` lets viem read at `latest`; `blockNumber` is only set for
74
+ // testnet forks pinned to a specific block.
75
+ blockNumber,
76
+ contracts: [...balanceContracts, preview]
77
+ });
78
+ } catch (cause) {
79
+ throw new PreviewSimulationError([
80
+ {
81
+ source: "multicall",
82
+ detail: decodeSimulationError({
83
+ error: cause instanceof Error ? cause : new Error(String(cause))
84
+ })
85
+ }
86
+ ]);
87
+ }
88
+ const previewAmount = results[balanceContracts.length];
89
+ const balances = new AddressMap();
90
+ for (const [i, { holder, token }] of balanceCalls.entries()) {
91
+ const tokenBalances = balances.get(holder) ?? new AddressMap();
92
+ tokenBalances.upsert(token, results[i]);
93
+ balances.upsert(holder, tokenBalances);
94
+ }
95
+ const before = (token, holder) => balances.get(holder)?.get(token) ?? 0n;
96
+ return {
97
+ status: "success",
98
+ balanceChanges: computePoolOpBalanceChanges(
99
+ operation,
100
+ wallet,
101
+ previewAmount,
102
+ before
103
+ )
104
+ };
105
+ } catch (cause) {
106
+ const error = asPreviewSimulationError(cause, "multicall");
107
+ logger?.error(error, "pool operation simulation failed");
108
+ return { status: "failure", error };
22
109
  }
23
- if (multicall.status === "fulfilled") {
24
- if (v1.status === "rejected") {
25
- logger?.debug(
26
- asPreviewSimulationError(v1.reason, "eth_simulateV1"),
27
- "eth_simulateV1 flow failed; falling back to multicall result"
28
- );
110
+ }
111
+ function balanceLegs(operation, wallet, previewAmount) {
112
+ const { pool, receiver } = operation;
113
+ switch (operation.operation) {
114
+ case "Deposit":
115
+ return [
116
+ { address: wallet, token: operation.tokenIn, delta: -operation.assets },
117
+ { address: receiver, token: pool, delta: previewAmount }
118
+ ];
119
+ case "Mint":
120
+ return [
121
+ { address: wallet, token: operation.tokenIn, delta: -previewAmount },
122
+ { address: receiver, token: pool, delta: operation.shares }
123
+ ];
124
+ case "Withdraw":
125
+ return [
126
+ { address: operation.owner, token: pool, delta: -previewAmount },
127
+ {
128
+ address: receiver,
129
+ token: operation.tokenOut,
130
+ delta: operation.assets
131
+ }
132
+ ];
133
+ case "Redeem":
134
+ return [
135
+ { address: operation.owner, token: pool, delta: -operation.shares },
136
+ { address: receiver, token: operation.tokenOut, delta: previewAmount }
137
+ ];
138
+ }
139
+ }
140
+ function computePoolOpBalanceChanges(operation, wallet, previewAmount, before) {
141
+ const byAddress = new AddressMap();
142
+ for (const { address, token, delta } of balanceLegs(
143
+ operation,
144
+ wallet,
145
+ previewAmount
146
+ )) {
147
+ const beforeBalance = before(token, address);
148
+ const change = {
149
+ token,
150
+ before: beforeBalance,
151
+ after: beforeBalance + delta,
152
+ delta
153
+ };
154
+ const existing = byAddress.get(address);
155
+ if (existing) {
156
+ existing.changes.push(change);
157
+ } else {
158
+ byAddress.upsert(address, { address, changes: [change] });
29
159
  }
30
- return { status: "success", ...multicall.value };
31
160
  }
32
- const error = combinePreviewSimulationErrors(
33
- v1.status === "rejected" ? asPreviewSimulationError(v1.reason, "eth_simulateV1") : void 0,
34
- asPreviewSimulationError(multicall.reason, "multicall")
35
- );
36
- logger?.error(error, "pool operation simulation failed");
37
- return { status: "failure", error };
161
+ return byAddress.values();
38
162
  }
39
163
  export {
164
+ computePoolOpBalanceChanges,
40
165
  simulatePoolOperation
41
166
  };
@@ -67,6 +67,7 @@ class MultichainSDK {
67
67
  const perChainOpts = options?.perChain?.[network] ?? {};
68
68
  return sdk.attach({
69
69
  ...perChainOpts,
70
+ loadZappers: perChainOpts.loadZappers ?? options?.loadZappers,
70
71
  redstone: {
71
72
  ...options?.redstone,
72
73
  cache: this.#redstoneCache,
@@ -126,7 +126,8 @@ class OnchainSDK extends ChainContractsRegister {
126
126
  ignoreMarkets,
127
127
  marketConfigurators: mcs,
128
128
  redstone,
129
- pyth
129
+ pyth,
130
+ loadZappers
130
131
  } = options ?? {};
131
132
  const marketConfigurators = mcs ?? TypedObjectUtils.keys(
132
133
  this.client.chain.defaultMarketConfigurators
@@ -195,6 +196,9 @@ class OnchainSDK extends ChainContractsRegister {
195
196
  blockNumber: this.currentBlock,
196
197
  gas: this.gasLimit
197
198
  });
199
+ if (loadZappers) {
200
+ await this.#marketRegister.loadZappers();
201
+ }
198
202
  }
199
203
  const pluginsList = TypedObjectUtils.entries(this.plugins);
200
204
  const pluginResponse = await Promise.allSettled(
@@ -247,7 +251,7 @@ class OnchainSDK extends ChainContractsRegister {
247
251
  `address provider version: ${this.#addressProvider.version}`
248
252
  );
249
253
  this.#marketRegister = new MarketRegister(this, ignoreMarkets);
250
- this.#marketRegister.hydrate(state.markets);
254
+ this.#marketRegister.hydrate(state);
251
255
  this.#rwa = new RWARegistry(this);
252
256
  this.#rwa.setState(state.rwa);
253
257
  for (const [name, plugin] of TypedObjectUtils.entries(this.plugins)) {
@@ -312,7 +316,7 @@ class OnchainSDK extends ChainContractsRegister {
312
316
  currentBlock: this.currentBlock,
313
317
  timestamp: this.timestamp,
314
318
  addressProvider: this.addressProvider.state,
315
- markets: this.marketRegister.state,
319
+ ...this.marketRegister.state,
316
320
  rwa: this.#rwa.state,
317
321
  plugins: Object.fromEntries(
318
322
  TypedObjectUtils.entries(this.plugins).map(([name, plugin]) => [
@@ -35,10 +35,11 @@ class MarketRegister extends ZapperRegister {
35
35
  * bypassing on-chain reads.
36
36
  * @param state - Array of market data snapshots.
37
37
  **/
38
- hydrate(state) {
39
- const configurators = new Set(state.map((m) => m.configurator));
38
+ hydrate({ markets, zappers }) {
39
+ const configurators = new Set(markets.map((m) => m.configurator));
40
40
  this.#setMarketFilter([...configurators]);
41
- this.#setMarkets(state);
41
+ this.#setMarkets(markets);
42
+ this.hydrateZappers(zappers);
42
43
  }
43
44
  /**
44
45
  * @internal
@@ -157,7 +158,10 @@ class MarketRegister extends ZapperRegister {
157
158
  * Serializable snapshot of all loaded markets, suitable for hydration.
158
159
  **/
159
160
  get state() {
160
- return this.markets.map((market) => market.state);
161
+ return {
162
+ markets: this.markets.map((market) => market.state),
163
+ zappers: this.zappersState
164
+ };
161
165
  }
162
166
  /**
163
167
  * Returns a human-readable snapshot of all markets.
@@ -165,7 +169,8 @@ class MarketRegister extends ZapperRegister {
165
169
  **/
166
170
  stateHuman(raw = true) {
167
171
  return {
168
- markets: this.markets.map((market) => market.stateHuman(raw))
172
+ markets: this.markets.map((market) => market.stateHuman(raw)),
173
+ zappers: this.zappersStateHuman(raw)
169
174
  };
170
175
  }
171
176
  /**
@@ -55,6 +55,60 @@ class ZapperRegister extends SDKConstruct {
55
55
  }
56
56
  }
57
57
  }
58
+ /**
59
+ * Serializable snapshot of all loaded zappers, suitable for hydration.
60
+ * Returns `undefined` when zappers were never loaded (i.e. `loadZappers` was
61
+ * not called), so the not-loaded state round-trips cleanly.
62
+ **/
63
+ get zappersState() {
64
+ if (!this.#zappers) {
65
+ return void 0;
66
+ }
67
+ return this.#zappers.values().flatMap(
68
+ (zappers) => zappers.map((z) => ({
69
+ pool: z.pool,
70
+ type: z.type,
71
+ baseParams: z.baseParams,
72
+ tokenIn: z.tokenIn,
73
+ tokenOut: z.tokenOut
74
+ }))
75
+ );
76
+ }
77
+ /**
78
+ * Restores zapper state from a previously serialized snapshot,
79
+ * bypassing on-chain reads.
80
+ * @param state - Array of zapper data snapshots, or `undefined` when zappers
81
+ * were not loaded in the snapshot (leaves the registry in the not-loaded state).
82
+ **/
83
+ hydrateZappers(state) {
84
+ if (!state) {
85
+ return;
86
+ }
87
+ this.#zappers = new AddressMap(void 0, "zappers");
88
+ for (const z of state) {
89
+ this.#addZapper(z);
90
+ }
91
+ }
92
+ /**
93
+ * Returns a human-readable snapshot of all loaded zappers.
94
+ * Returns `undefined` when zappers were never loaded.
95
+ * @param raw - When `true`, includes raw/unformatted values.
96
+ **/
97
+ zappersStateHuman(_ = true) {
98
+ if (!this.#zappers) {
99
+ return void 0;
100
+ }
101
+ return this.#zappers.values().flatMap(
102
+ (zappers) => zappers.map((z) => ({
103
+ address: this.labelAddress(z.baseParams.addr),
104
+ contractType: z.contractType,
105
+ type: z.type,
106
+ pool: this.labelAddress(z.pool),
107
+ tokenIn: this.sdk.labelAddress(z.tokenIn.addr),
108
+ tokenOut: this.sdk.labelAddress(z.tokenOut.addr)
109
+ }))
110
+ );
111
+ }
58
112
  #addZapper(z) {
59
113
  const zapper = createZapper(this.sdk, z);
60
114
  const existing = this.zappers.get(z.pool);
@@ -1,4 +1,6 @@
1
- import { decodeAbiParameters } from "viem";
1
+ import {
2
+ decodeAbiParameters
3
+ } from "viem";
2
4
  import { iSecuritizeRWAFactoryAbi } from "../../../../abi/rwa/iSecuritizeRWAFactory.js";
3
5
  import { BaseContract } from "../../../base/index.js";
4
6
  import { AddressMap, AddressSet } from "../../../utils/index.js";
@@ -49,6 +51,26 @@ class SecuritizeRWAFactory extends BaseContract {
49
51
  operators: [...t.operators]
50
52
  }));
51
53
  }
54
+ parseFunctionParamsV2(params, strict) {
55
+ switch (params.functionName) {
56
+ case "openCreditAccount": {
57
+ const [creditManager, calls] = params.args;
58
+ return {
59
+ creditManager,
60
+ calls: this.register.parseMultiCallV2([...calls], strict)
61
+ };
62
+ }
63
+ case "multicall": {
64
+ const [creditAccount, calls] = params.args;
65
+ return {
66
+ creditAccount,
67
+ calls: this.register.parseMultiCallV2([...calls], strict)
68
+ };
69
+ }
70
+ default:
71
+ return super.parseFunctionParamsV2(params, strict);
72
+ }
73
+ }
52
74
  /**
53
75
  * {@inheritDoc IRWAFactory.decodeInvestorData}
54
76
  */
@@ -1,25 +1,9 @@
1
1
  import { ierc20ZapperAbi } from "../../../abi/iERC20Zapper.js";
2
- import { BaseContract } from "../../base/index.js";
2
+ import { ZapperContract } from "./ZapperContract.js";
3
3
  const abi = ierc20ZapperAbi;
4
- class IERC20ZapperContract extends BaseContract {
5
- pool;
6
- type;
7
- baseParams;
8
- tokenIn;
9
- tokenOut;
4
+ class IERC20ZapperContract extends ZapperContract {
10
5
  constructor(sdk, data) {
11
- super(sdk, {
12
- addr: data.baseParams.addr,
13
- abi,
14
- name: `ERC20Zapper(${sdk.labelAddress(data.baseParams.addr)})`,
15
- version: data.baseParams.version,
16
- contractType: data.baseParams.contractType
17
- });
18
- this.pool = data.pool;
19
- this.type = data.type;
20
- this.baseParams = data.baseParams;
21
- this.tokenIn = data.tokenIn;
22
- this.tokenOut = data.tokenOut;
6
+ super(sdk, data, abi, "ERC20Zapper");
23
7
  }
24
8
  /**
25
9
  * Deposits ERC20 tokens into the pool via this zapper.
@@ -49,25 +33,6 @@ class IERC20ZapperContract extends BaseContract {
49
33
  args: [tokenInAmount, receiver, referralCode, deadline, v, r, s]
50
34
  });
51
35
  }
52
- /**
53
- * Redeems pool shares (diesel tokens) for the underlying asset via this zapper.
54
- */
55
- redeem(tokenInAmount, receiver) {
56
- return this.createRawTx({
57
- functionName: "redeem",
58
- args: [tokenInAmount, receiver]
59
- });
60
- }
61
- /**
62
- * Redeems pool shares via this zapper with an EIP-2612 permit signature,
63
- * skipping a separate approve transaction.
64
- */
65
- redeemWithPermit(tokenInAmount, receiver, deadline, v, r, s) {
66
- return this.createRawTx({
67
- functionName: "redeemWithPermit",
68
- args: [tokenInAmount, receiver, deadline, v, r, s]
69
- });
70
- }
71
36
  }
72
37
  export {
73
38
  IERC20ZapperContract
@@ -1,25 +1,9 @@
1
1
  import { iethZapperAbi } from "../../../abi/iETHZapper.js";
2
- import { BaseContract } from "../../base/index.js";
2
+ import { ZapperContract } from "./ZapperContract.js";
3
3
  const abi = iethZapperAbi;
4
- class IETHZapperContract extends BaseContract {
5
- pool;
6
- type;
7
- baseParams;
8
- tokenIn;
9
- tokenOut;
4
+ class IETHZapperContract extends ZapperContract {
10
5
  constructor(sdk, data) {
11
- super(sdk, {
12
- addr: data.baseParams.addr,
13
- abi,
14
- name: `ETHZapper(${sdk.labelAddress(data.baseParams.addr)})`,
15
- version: data.baseParams.version,
16
- contractType: data.baseParams.contractType
17
- });
18
- this.pool = data.pool;
19
- this.type = data.type;
20
- this.baseParams = data.baseParams;
21
- this.tokenIn = data.tokenIn;
22
- this.tokenOut = data.tokenOut;
6
+ super(sdk, data, abi, "ETHZapper");
23
7
  }
24
8
  /**
25
9
  * Deposits native ETH into the pool via this zapper.
@@ -40,25 +24,6 @@ class IETHZapperContract extends BaseContract {
40
24
  args: [receiver, referralCode]
41
25
  });
42
26
  }
43
- /**
44
- * Redeems pool shares (diesel tokens) for the underlying asset via this zapper.
45
- */
46
- redeem(tokenInAmount, receiver) {
47
- return this.createRawTx({
48
- functionName: "redeem",
49
- args: [tokenInAmount, receiver]
50
- });
51
- }
52
- /**
53
- * Redeems pool shares via this zapper with an EIP-2612 permit signature,
54
- * skipping a separate approve transaction.
55
- */
56
- redeemWithPermit(tokenInAmount, receiver, deadline, v, r, s) {
57
- return this.createRawTx({
58
- functionName: "redeemWithPermit",
59
- args: [tokenInAmount, receiver, deadline, v, r, s]
60
- });
61
- }
62
27
  }
63
28
  export {
64
29
  IETHZapperContract
@@ -0,0 +1,85 @@
1
+ import { iZapperAbi } from "../../../abi/iZapper.js";
2
+ import { BaseContract } from "../../base/index.js";
3
+ import { UnsupportedZapperFunctionError } from "./errors.js";
4
+ class ZapperContract extends BaseContract {
5
+ sdk;
6
+ pool;
7
+ type;
8
+ baseParams;
9
+ tokenIn;
10
+ tokenOut;
11
+ constructor(sdk, data, abi = iZapperAbi, namePrefix = "Zapper") {
12
+ super(sdk, {
13
+ addr: data.baseParams.addr,
14
+ abi,
15
+ name: `${namePrefix}(${sdk.labelAddress(data.baseParams.addr)})`,
16
+ version: data.baseParams.version,
17
+ contractType: data.baseParams.contractType
18
+ });
19
+ this.sdk = sdk;
20
+ this.pool = data.pool;
21
+ this.type = data.type;
22
+ this.baseParams = data.baseParams;
23
+ this.tokenIn = data.tokenIn;
24
+ this.tokenOut = data.tokenOut;
25
+ }
26
+ /**
27
+ * Decodes zapper calldata into {@link ParsedZapperOperation}.
28
+ * Throws {@link UnsupportedZapperFunctionError} for unknown selectors.
29
+ */
30
+ parseOperation(calldata, value) {
31
+ const parsed = this.parseFunctionDataV2(calldata);
32
+ const { rawArgs } = parsed;
33
+ const pool = this.pool;
34
+ const zapper = this.address;
35
+ const token = this.tokenIn.addr;
36
+ const underlying = this.sdk.marketRegister.findByPool(pool).underlying;
37
+ const receiver = rawArgs.receiver;
38
+ if (parsed.functionName.startsWith("deposit")) {
39
+ return {
40
+ operation: "Deposit",
41
+ pool,
42
+ zapper,
43
+ receiver,
44
+ assets: rawArgs.tokenInAmount ?? value ?? 0n,
45
+ token,
46
+ underlying,
47
+ referralCode: rawArgs.referralCode
48
+ };
49
+ }
50
+ if (parsed.functionName.startsWith("redeem")) {
51
+ return {
52
+ operation: "Redeem",
53
+ pool,
54
+ zapper,
55
+ receiver,
56
+ shares: rawArgs.tokenOutAmount,
57
+ token,
58
+ underlying
59
+ };
60
+ }
61
+ throw new UnsupportedZapperFunctionError(zapper, parsed.functionName);
62
+ }
63
+ /**
64
+ * Redeems pool shares (diesel tokens) for the underlying asset via this zapper.
65
+ */
66
+ redeem(tokenInAmount, receiver) {
67
+ return this.createRawTx({
68
+ functionName: "redeem",
69
+ args: [tokenInAmount, receiver]
70
+ });
71
+ }
72
+ /**
73
+ * Redeems pool shares via this zapper with an EIP-2612 permit signature,
74
+ * skipping a separate approve transaction.
75
+ */
76
+ redeemWithPermit(tokenInAmount, receiver, deadline, v, r, s) {
77
+ return this.createRawTx({
78
+ functionName: "redeemWithPermit",
79
+ args: [tokenInAmount, receiver, deadline, v, r, s]
80
+ });
81
+ }
82
+ }
83
+ export {
84
+ ZapperContract
85
+ };
@@ -1,20 +1,28 @@
1
+ import { bytes32ToString } from "../../utils/index.js";
1
2
  import { IERC20ZapperContract } from "./IERC20ZapperContract.js";
2
3
  import { IETHZapperContract } from "./IETHZapperContract.js";
3
- import { Zapper } from "./Zapper.js";
4
+ import { ZapperContract } from "./ZapperContract.js";
4
5
  function createZapper(sdk, data) {
6
+ const existing = sdk.getContract(data.baseParams.addr);
7
+ if (existing) {
8
+ return existing;
9
+ }
5
10
  if (data.type === "base") {
6
- const contractType = Zapper.contractType(data.baseParams);
11
+ const contractType = bytes32ToString(data.baseParams.contractType);
7
12
  switch (contractType) {
8
13
  case "ZAPPER::ERC4626_UNDERLYING":
9
14
  return new IERC20ZapperContract(sdk, data);
10
15
  case "ZAPPER::WETH_DEPOSIT":
11
16
  return new IETHZapperContract(sdk, data);
12
17
  default:
18
+ if (sdk.strictContractTypes) {
19
+ throw new Error(`Unknown zapper contract type: ${contractType}`);
20
+ }
13
21
  sdk.logger?.warn(`Unknown zapper contract type: ${contractType}`);
14
- return new Zapper(data);
22
+ return new ZapperContract(sdk, data);
15
23
  }
16
24
  }
17
- return new Zapper(data);
25
+ return new ZapperContract(sdk, data);
18
26
  }
19
27
  export {
20
28
  createZapper
@@ -0,0 +1,13 @@
1
+ class UnsupportedZapperFunctionError extends Error {
2
+ zapper;
3
+ functionName;
4
+ constructor(zapper, functionName) {
5
+ super(`unsupported zapper function "${functionName}" on ${zapper}`);
6
+ this.name = "UnsupportedZapperFunctionError";
7
+ this.zapper = zapper;
8
+ this.functionName = functionName;
9
+ }
10
+ }
11
+ export {
12
+ UnsupportedZapperFunctionError
13
+ };
@@ -1,4 +1,6 @@
1
1
  export * from "./createZapper.js";
2
+ export * from "./errors.js";
2
3
  export * from "./IERC20ZapperContract.js";
3
4
  export * from "./IETHZapperContract.js";
4
- export * from "./Zapper.js";
5
+ export * from "./types.js";
6
+ export * from "./ZapperContract.js";
File without changes