@morpho-org/consumer-sdk 0.3.0 → 0.4.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.
- package/README.md +178 -44
- package/lib/actions/index.d.ts +1 -0
- package/lib/actions/index.js +1 -0
- package/lib/actions/requirements/getRequirements.js +3 -0
- package/lib/actions/requirements/getRequirementsAction.d.ts +2 -2
- package/lib/actions/requirements/getRequirementsAction.js +7 -7
- package/lib/actions/vaultV1/deposit.d.ts +41 -0
- package/lib/actions/vaultV1/deposit.js +116 -0
- package/lib/actions/vaultV1/index.d.ts +3 -0
- package/lib/actions/vaultV1/index.js +19 -0
- package/lib/actions/vaultV1/redeem.d.ts +29 -0
- package/lib/actions/vaultV1/redeem.js +48 -0
- package/lib/actions/vaultV1/withdraw.d.ts +29 -0
- package/lib/actions/vaultV1/withdraw.js +48 -0
- package/lib/actions/vaultV2/deposit.d.ts +20 -25
- package/lib/actions/vaultV2/deposit.js +78 -40
- package/lib/actions/vaultV2/forceRedeem.js +2 -2
- package/lib/actions/vaultV2/forceWithdraw.d.ts +2 -2
- package/lib/actions/vaultV2/forceWithdraw.js +8 -8
- package/lib/actions/vaultV2/redeem.js +2 -2
- package/lib/actions/vaultV2/withdraw.d.ts +3 -3
- package/lib/actions/vaultV2/withdraw.js +6 -6
- package/lib/client/morphoClient.d.ts +2 -1
- package/lib/client/morphoClient.js +3 -0
- package/lib/client/morphoViemExtension.d.ts +12 -9
- package/lib/client/morphoViemExtension.js +12 -9
- package/lib/entities/index.d.ts +1 -0
- package/lib/entities/index.js +1 -0
- package/lib/entities/vaultV1/index.d.ts +1 -0
- package/lib/entities/vaultV1/index.js +17 -0
- package/lib/entities/vaultV1/vaultV1.d.ts +95 -0
- package/lib/entities/vaultV1/vaultV1.js +125 -0
- package/lib/entities/vaultV2/vaultV2.d.ts +24 -21
- package/lib/entities/vaultV2/vaultV2.js +39 -16
- package/lib/helpers/encodeDeallocation.js +3 -3
- package/lib/types/action.d.ts +39 -4
- package/lib/types/client.d.ts +2 -1
- package/lib/types/deallocation.d.ts +1 -1
- package/lib/types/error.d.ts +22 -4
- package/lib/types/error.js +48 -12
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Consumer
|
|
1
|
+
# Consumer SDK
|
|
2
2
|
|
|
3
3
|

|
|
4
4
|
|
|
@@ -6,82 +6,216 @@
|
|
|
6
6
|
|
|
7
7
|
> **The abstraction layer that simplifies Morpho protocol**
|
|
8
8
|
|
|
9
|
-
##
|
|
9
|
+
## Entities & Actions
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
| Entity | Action | Route | Why |
|
|
12
|
+
| ----------- | --------------- | ------------------------- | --------------------------------------------------------------------------------------- |
|
|
13
|
+
| **VaultV2** | `deposit` | Bundler (general adapter) | Enforces `maxSharePrice` — inflation attack prevention. Supports native token wrapping. |
|
|
14
|
+
| | `withdraw` | Direct vault call | No attack surface, no bundler overhead needed |
|
|
15
|
+
| | `redeem` | Direct vault call | No attack surface, no bundler overhead needed |
|
|
16
|
+
| | `forceWithdraw` | Vault `multicall` | N `forceDeallocate` + 1 `withdraw` in a single tx |
|
|
17
|
+
| | `forceRedeem` | Vault `multicall` | N `forceDeallocate` + 1 `redeem` in a single tx |
|
|
18
|
+
| **VaultV1** | `deposit` | Bundler (general adapter) | Same ERC-4626 inflation attack prevention as V2. Supports native token wrapping. |
|
|
19
|
+
| | `withdraw` | Direct vault call | No attack surface |
|
|
20
|
+
| | `redeem` | Direct vault call | No attack surface |
|
|
21
|
+
|
|
22
|
+
## VaultV2
|
|
12
23
|
|
|
13
24
|
```typescript
|
|
14
25
|
import { MorphoClient } from "@morpho-org/consumer-sdk";
|
|
15
|
-
import {
|
|
26
|
+
import { createPublicClient, http } from "viem";
|
|
27
|
+
import { mainnet } from "viem/chains";
|
|
28
|
+
|
|
29
|
+
const viemClient = createPublicClient({ chain: mainnet, transport: http() });
|
|
30
|
+
const morpho = new MorphoClient(viemClient);
|
|
31
|
+
|
|
32
|
+
const vault = morpho.vaultV2("0xVault...", 1);
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### Deposit
|
|
36
|
+
|
|
37
|
+
```typescript
|
|
38
|
+
const { buildTx, getRequirements } = await vault.deposit({
|
|
39
|
+
amount: 1000000000000000000n,
|
|
40
|
+
userAddress: "0xUser...",
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
const requirements = await getRequirements();
|
|
44
|
+
const tx = buildTx(requirementSignature);
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
#### Deposit with native token wrapping
|
|
48
|
+
|
|
49
|
+
For vaults whose underlying asset is wNative, you can deposit native token that will be automatically wrapped:
|
|
50
|
+
|
|
51
|
+
```typescript
|
|
52
|
+
// Native ETH only — wraps 1 ETH to WETH and deposits
|
|
53
|
+
const { buildTx, getRequirements } = await vault.deposit({
|
|
54
|
+
nativeAmount: 1000000000000000000n,
|
|
55
|
+
userAddress: "0xUser...",
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
// Mixed — 0.5 WETH (ERC-20) + 0.5 native ETH wrapped to WETH
|
|
59
|
+
const { buildTx, getRequirements } = await vault.deposit({
|
|
60
|
+
amount: 500000000000000000n,
|
|
61
|
+
nativeAmount: 500000000000000000n,
|
|
62
|
+
userAddress: "0xUser...",
|
|
63
|
+
});
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
The bundler atomically transfers native token, wraps it to wNative, and deposits alongside any ERC-20 amount. The transaction's `value` field is set to `nativeAmount`.
|
|
67
|
+
|
|
68
|
+
### Withdraw
|
|
69
|
+
|
|
70
|
+
```typescript
|
|
71
|
+
const { buildTx } = vault.withdraw({
|
|
72
|
+
amount: 500000000000000000n,
|
|
73
|
+
userAddress: "0xUser...",
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
const tx = buildTx();
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Redeem
|
|
16
80
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
81
|
+
```typescript
|
|
82
|
+
const { buildTx } = vault.redeem({
|
|
83
|
+
shares: 1000000000000000000n,
|
|
84
|
+
userAddress: "0xUser...",
|
|
21
85
|
});
|
|
22
86
|
|
|
23
|
-
const
|
|
87
|
+
const tx = buildTx();
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### Force Withdraw
|
|
24
91
|
|
|
25
|
-
|
|
26
|
-
const
|
|
27
|
-
|
|
28
|
-
|
|
92
|
+
```typescript
|
|
93
|
+
const { buildTx } = vault.forceWithdraw({
|
|
94
|
+
deallocations: [{ adapter: "0xAdapter...", amount: 100n }],
|
|
95
|
+
withdraw: { amount: 500000000000000000n },
|
|
96
|
+
userAddress: "0xUser...",
|
|
29
97
|
});
|
|
30
|
-
console.log(deposit.buildTx());
|
|
31
|
-
console.log(await deposit.getRequirements());
|
|
32
98
|
|
|
33
|
-
const
|
|
34
|
-
|
|
35
|
-
|
|
99
|
+
const tx = buildTx();
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### Force Redeem
|
|
103
|
+
|
|
104
|
+
```typescript
|
|
105
|
+
const { buildTx } = vault.forceRedeem({
|
|
106
|
+
deallocations: [{ adapter: "0xAdapter...", amount: 100n }],
|
|
107
|
+
redeem: { shares: 1000000000000000000n },
|
|
108
|
+
userAddress: "0xUser...",
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
const tx = buildTx();
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## VaultV1
|
|
115
|
+
|
|
116
|
+
```typescript
|
|
117
|
+
const vault = morpho.vaultV1("0xVault...", 1);
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### Deposit
|
|
121
|
+
|
|
122
|
+
```typescript
|
|
123
|
+
const { buildTx, getRequirements } = await vault.deposit({
|
|
124
|
+
amount: 1000000000000000000n,
|
|
125
|
+
userAddress: "0xUser...",
|
|
36
126
|
});
|
|
37
|
-
console.log(withdraw.buildTx());
|
|
38
127
|
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
-
|
|
128
|
+
const requirements = await getRequirements();
|
|
129
|
+
const tx = buildTx(requirementSignature);
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### Withdraw
|
|
133
|
+
|
|
134
|
+
```typescript
|
|
135
|
+
const { buildTx } = vault.withdraw({
|
|
136
|
+
amount: 500000000000000000n,
|
|
137
|
+
userAddress: "0xUser...",
|
|
42
138
|
});
|
|
43
|
-
|
|
139
|
+
|
|
140
|
+
const tx = buildTx();
|
|
44
141
|
```
|
|
45
142
|
|
|
46
|
-
###
|
|
143
|
+
### Redeem
|
|
47
144
|
|
|
48
145
|
```typescript
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
vault: {
|
|
53
|
-
chainId: mainnet.id,
|
|
54
|
-
address: "0x1234...", // vault address
|
|
55
|
-
asset: "0x1234...", // asset address
|
|
56
|
-
},
|
|
57
|
-
args: {
|
|
58
|
-
assets: 1000000000000000000n, // vault asset amount
|
|
59
|
-
maxSharePrice: 995180497664595699494513674403n,
|
|
60
|
-
recipient: "0x1234...", // recipient address
|
|
61
|
-
},
|
|
146
|
+
const { buildTx } = vault.redeem({
|
|
147
|
+
shares: 1000000000000000000n,
|
|
148
|
+
userAddress: "0xUser...",
|
|
62
149
|
});
|
|
150
|
+
|
|
151
|
+
const tx = buildTx();
|
|
63
152
|
```
|
|
64
153
|
|
|
65
|
-
##
|
|
154
|
+
## Architecture
|
|
155
|
+
|
|
156
|
+
```mermaid
|
|
157
|
+
graph LR
|
|
158
|
+
MC[MorphoClient]
|
|
159
|
+
|
|
160
|
+
MC -->|.vaultV1| MV1
|
|
161
|
+
MC -->|.vaultV2| MV2
|
|
162
|
+
|
|
163
|
+
subgraph VaultV1 Flow
|
|
164
|
+
MV1[MorphoVaultV1]
|
|
165
|
+
MV1 --> V1D[vaultV1Deposit]
|
|
166
|
+
MV1 --> V1W[vaultV1Withdraw]
|
|
167
|
+
MV1 --> V1R[vaultV1Redeem]
|
|
168
|
+
|
|
169
|
+
V1D -->|nativeTransfer + wrapNative + erc4626Deposit| B1[Bundler3]
|
|
170
|
+
V1W -->|direct call| MM[MetaMorpho]
|
|
171
|
+
V1R -->|direct call| MM
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
subgraph VaultV2 Flow
|
|
175
|
+
MV2[MorphoVaultV2]
|
|
176
|
+
MV2 --> V2D[vaultV2Deposit]
|
|
177
|
+
MV2 --> V2W[vaultV2Withdraw]
|
|
178
|
+
MV2 --> V2R[vaultV2Redeem]
|
|
179
|
+
MV2 --> V2FW[vaultV2ForceWithdraw]
|
|
180
|
+
MV2 --> V2FR[vaultV2ForceRedeem]
|
|
181
|
+
|
|
182
|
+
V2D -->|nativeTransfer + wrapNative + erc4626Deposit| B2[Bundler3]
|
|
183
|
+
V2W -->|direct call| V2C[VaultV2 Contract]
|
|
184
|
+
V2R -->|direct call| V2C
|
|
185
|
+
V2FW -->|multicall| V2C
|
|
186
|
+
V2FR -->|multicall| V2C
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
subgraph Shared
|
|
190
|
+
REQ[getRequirements]
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
MV1 -.->|approval / permit| REQ
|
|
194
|
+
MV2 -.->|approval / permit| REQ
|
|
195
|
+
|
|
196
|
+
style B1 fill:#e8f5e9,stroke:#4caf50
|
|
197
|
+
style B2 fill:#e8f5e9,stroke:#4caf50
|
|
198
|
+
style MM fill:#fff3e0,stroke:#ff9800
|
|
199
|
+
style V2C fill:#e3f2fd,stroke:#2196f3
|
|
200
|
+
style REQ fill:#f3e5f5,stroke:#9c27b0
|
|
201
|
+
```
|
|
66
202
|
|
|
67
|
-
|
|
203
|
+
## Local Development
|
|
68
204
|
|
|
69
|
-
|
|
205
|
+
Link this package to your app for local debugging:
|
|
70
206
|
|
|
71
207
|
```bash
|
|
72
208
|
# In this consumer-sdk project
|
|
73
209
|
pnpm run build:link
|
|
74
210
|
```
|
|
75
211
|
|
|
76
|
-
|
|
212
|
+
In your other project:
|
|
77
213
|
|
|
78
214
|
```bash
|
|
79
215
|
# Link the local package
|
|
80
216
|
pnpm link consumer-sdk
|
|
81
217
|
```
|
|
82
218
|
|
|
83
|
-
##
|
|
219
|
+
## Contributing
|
|
84
220
|
|
|
85
221
|
Contributions are welcome! Feel free to open an issue or PR.
|
|
86
|
-
|
|
87
|
-
**Made with ❤️ by the Morpho team**
|
package/lib/actions/index.d.ts
CHANGED
package/lib/actions/index.js
CHANGED
|
@@ -15,4 +15,5 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
17
|
__exportStar(require("./requirements"), exports);
|
|
18
|
+
__exportStar(require("./vaultV1"), exports);
|
|
18
19
|
__exportStar(require("./vaultV2"), exports);
|
|
@@ -32,6 +32,9 @@ const getRequirements = async (viemClient, params) => {
|
|
|
32
32
|
if (viemClient.chain?.id !== chainId) {
|
|
33
33
|
throw new types_1.ChainIdMismatchError(viemClient.chain?.id, chainId);
|
|
34
34
|
}
|
|
35
|
+
if (amount === 0n) {
|
|
36
|
+
return [];
|
|
37
|
+
}
|
|
35
38
|
const { permit2, dai, bundler3: { generalAdapter1 }, } = (0, blue_sdk_1.getChainAddresses)(chainId);
|
|
36
39
|
const { erc20Allowances, erc2612Nonce, permit2BundlerAllowance } = await (0, blue_sdk_viem_1.fetchHolding)(from, address, viemClient, {
|
|
37
40
|
deployless: params.supportDeployless,
|
|
@@ -4,7 +4,7 @@ import { type Permit2Action, type PermitAction, type PermitArgs } from "../../ty
|
|
|
4
4
|
interface GetRequirementsActionParams {
|
|
5
5
|
chainId: number;
|
|
6
6
|
asset: Address;
|
|
7
|
-
|
|
7
|
+
amount: bigint;
|
|
8
8
|
requirementSignature: {
|
|
9
9
|
args: PermitArgs;
|
|
10
10
|
action: PermitAction | Permit2Action;
|
|
@@ -13,5 +13,5 @@ interface GetRequirementsActionParams {
|
|
|
13
13
|
/**
|
|
14
14
|
* Get the actions required to transfer the asset based on the requirement signature.
|
|
15
15
|
*/
|
|
16
|
-
export declare const getRequirementsAction: ({ chainId, asset,
|
|
16
|
+
export declare const getRequirementsAction: ({ chainId, asset, amount, requirementSignature, }: GetRequirementsActionParams) => Action[];
|
|
17
17
|
export {};
|
|
@@ -7,12 +7,12 @@ const types_1 = require("../../types");
|
|
|
7
7
|
/**
|
|
8
8
|
* Get the actions required to transfer the asset based on the requirement signature.
|
|
9
9
|
*/
|
|
10
|
-
const getRequirementsAction = ({ chainId, asset,
|
|
10
|
+
const getRequirementsAction = ({ chainId, asset, amount, requirementSignature, }) => {
|
|
11
11
|
if (!(0, viem_1.isAddressEqual)(requirementSignature.args.asset, asset)) {
|
|
12
12
|
throw new types_1.DepositAssetMismatchError(asset, requirementSignature.args.asset);
|
|
13
13
|
}
|
|
14
|
-
if (requirementSignature.args.amount !==
|
|
15
|
-
throw new types_1.DepositAmountMismatchError(
|
|
14
|
+
if (requirementSignature.args.amount !== amount) {
|
|
15
|
+
throw new types_1.DepositAmountMismatchError(amount, requirementSignature.args.amount);
|
|
16
16
|
}
|
|
17
17
|
const { bundler3: { generalAdapter1 }, } = (0, blue_sdk_1.getChainAddresses)(chainId);
|
|
18
18
|
if (requirementSignature.action.type === "permit2") {
|
|
@@ -34,12 +34,12 @@ const getRequirementsAction = ({ chainId, asset, assets, requirementSignature, }
|
|
|
34
34
|
sigDeadline: requirementSignature.args.deadline,
|
|
35
35
|
},
|
|
36
36
|
requirementSignature.args.signature,
|
|
37
|
-
false
|
|
37
|
+
false /* skipRevert */,
|
|
38
38
|
],
|
|
39
39
|
},
|
|
40
40
|
{
|
|
41
41
|
type: "transferFrom2",
|
|
42
|
-
args: [asset,
|
|
42
|
+
args: [asset, amount, generalAdapter1, false /* skipRevert */],
|
|
43
43
|
},
|
|
44
44
|
];
|
|
45
45
|
}
|
|
@@ -52,12 +52,12 @@ const getRequirementsAction = ({ chainId, asset, assets, requirementSignature, }
|
|
|
52
52
|
requirementSignature.args.amount,
|
|
53
53
|
requirementSignature.args.deadline,
|
|
54
54
|
requirementSignature.args.signature,
|
|
55
|
-
false
|
|
55
|
+
false /* skipRevert */,
|
|
56
56
|
],
|
|
57
57
|
},
|
|
58
58
|
{
|
|
59
59
|
type: "erc20TransferFrom",
|
|
60
|
-
args: [asset,
|
|
60
|
+
args: [asset, amount, generalAdapter1, false /* skipRevert */],
|
|
61
61
|
},
|
|
62
62
|
];
|
|
63
63
|
};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { type Address } from "viem";
|
|
2
|
+
import { type DepositAmountArgs, type Metadata, type RequirementSignature, type Transaction, type VaultV1DepositAction } from "../../types";
|
|
3
|
+
export interface VaultV1DepositParams {
|
|
4
|
+
vault: {
|
|
5
|
+
chainId: number;
|
|
6
|
+
address: Address;
|
|
7
|
+
asset: Address;
|
|
8
|
+
};
|
|
9
|
+
args: DepositAmountArgs & {
|
|
10
|
+
maxSharePrice: bigint;
|
|
11
|
+
recipient: Address;
|
|
12
|
+
requirementSignature?: RequirementSignature;
|
|
13
|
+
};
|
|
14
|
+
metadata?: Metadata;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Prepares a deposit transaction for a VaultV1 (MetaMorpho) contract.
|
|
18
|
+
*
|
|
19
|
+
* Routed through the bundler to atomically execute the asset transfer and vault deposit.
|
|
20
|
+
* The general adapter enforces `maxSharePrice` on-chain to prevent inflation attacks.
|
|
21
|
+
* Never bypass the general adapter.
|
|
22
|
+
*
|
|
23
|
+
* When `nativeAmount` is provided, that amount of native ETH is sent as `msg.value`
|
|
24
|
+
* to the Bundler3 multicall and wrapped into WETH via `GeneralAdapter1.wrapNative()`.
|
|
25
|
+
* The vault's underlying asset must be the chain's wrapped native token (wNative).
|
|
26
|
+
*
|
|
27
|
+
* @param {Object} params - The deposit parameters.
|
|
28
|
+
* @param {Object} params.vault - The vault identifiers.
|
|
29
|
+
* @param {number} params.vault.chainId - The chain ID.
|
|
30
|
+
* @param {Address} params.vault.address - The vault address.
|
|
31
|
+
* @param {Address} params.vault.asset - The underlying ERC20 asset address.
|
|
32
|
+
* @param {Object} params.args - The deposit arguments.
|
|
33
|
+
* @param {bigint} [params.args.amount=0n] - Amount of ERC-20 assets to deposit. At least one of amount or nativeAmount must be provided.
|
|
34
|
+
* @param {bigint} params.args.maxSharePrice - Maximum acceptable share price (slippage protection).
|
|
35
|
+
* @param {Address} params.args.recipient - Receives the vault shares.
|
|
36
|
+
* @param {RequirementSignature} [params.args.requirementSignature] - Pre-signed permit/permit2 approval.
|
|
37
|
+
* @param {bigint} [params.args.nativeAmount] - Amount of native token to wrap into wNative for the deposit.
|
|
38
|
+
* @param {Metadata} [params.metadata] - Optional analytics metadata.
|
|
39
|
+
* @returns {Readonly<Transaction<VaultV1DepositAction>>} The prepared deposit transaction.
|
|
40
|
+
*/
|
|
41
|
+
export declare const vaultV1Deposit: ({ vault: { chainId, address: vaultAddress, asset }, args: { amount, maxSharePrice, recipient, requirementSignature, nativeAmount, }, metadata, }: VaultV1DepositParams) => Readonly<Transaction<VaultV1DepositAction>>;
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.vaultV1Deposit = void 0;
|
|
4
|
+
const blue_sdk_1 = require("@morpho-org/blue-sdk");
|
|
5
|
+
const bundler_sdk_viem_1 = require("@morpho-org/bundler-sdk-viem");
|
|
6
|
+
const morpho_ts_1 = require("@morpho-org/morpho-ts");
|
|
7
|
+
const viem_1 = require("viem");
|
|
8
|
+
const helpers_1 = require("../../helpers");
|
|
9
|
+
const types_1 = require("../../types");
|
|
10
|
+
const getRequirementsAction_1 = require("../requirements/getRequirementsAction");
|
|
11
|
+
/**
|
|
12
|
+
* Prepares a deposit transaction for a VaultV1 (MetaMorpho) contract.
|
|
13
|
+
*
|
|
14
|
+
* Routed through the bundler to atomically execute the asset transfer and vault deposit.
|
|
15
|
+
* The general adapter enforces `maxSharePrice` on-chain to prevent inflation attacks.
|
|
16
|
+
* Never bypass the general adapter.
|
|
17
|
+
*
|
|
18
|
+
* When `nativeAmount` is provided, that amount of native ETH is sent as `msg.value`
|
|
19
|
+
* to the Bundler3 multicall and wrapped into WETH via `GeneralAdapter1.wrapNative()`.
|
|
20
|
+
* The vault's underlying asset must be the chain's wrapped native token (wNative).
|
|
21
|
+
*
|
|
22
|
+
* @param {Object} params - The deposit parameters.
|
|
23
|
+
* @param {Object} params.vault - The vault identifiers.
|
|
24
|
+
* @param {number} params.vault.chainId - The chain ID.
|
|
25
|
+
* @param {Address} params.vault.address - The vault address.
|
|
26
|
+
* @param {Address} params.vault.asset - The underlying ERC20 asset address.
|
|
27
|
+
* @param {Object} params.args - The deposit arguments.
|
|
28
|
+
* @param {bigint} [params.args.amount=0n] - Amount of ERC-20 assets to deposit. At least one of amount or nativeAmount must be provided.
|
|
29
|
+
* @param {bigint} params.args.maxSharePrice - Maximum acceptable share price (slippage protection).
|
|
30
|
+
* @param {Address} params.args.recipient - Receives the vault shares.
|
|
31
|
+
* @param {RequirementSignature} [params.args.requirementSignature] - Pre-signed permit/permit2 approval.
|
|
32
|
+
* @param {bigint} [params.args.nativeAmount] - Amount of native token to wrap into wNative for the deposit.
|
|
33
|
+
* @param {Metadata} [params.metadata] - Optional analytics metadata.
|
|
34
|
+
* @returns {Readonly<Transaction<VaultV1DepositAction>>} The prepared deposit transaction.
|
|
35
|
+
*/
|
|
36
|
+
const vaultV1Deposit = ({ vault: { chainId, address: vaultAddress, asset }, args: { amount = 0n, maxSharePrice, recipient, requirementSignature, nativeAmount, }, metadata, }) => {
|
|
37
|
+
if (amount < 0n) {
|
|
38
|
+
throw new types_1.NonPositiveAssetAmountError(asset);
|
|
39
|
+
}
|
|
40
|
+
if (maxSharePrice <= 0n) {
|
|
41
|
+
throw new types_1.NonPositiveMaxSharePriceError(vaultAddress);
|
|
42
|
+
}
|
|
43
|
+
const actions = [];
|
|
44
|
+
const { bundler3: { generalAdapter1, bundler3 }, wNative, } = (0, blue_sdk_1.getChainAddresses)(chainId);
|
|
45
|
+
if (nativeAmount) {
|
|
46
|
+
if (nativeAmount < 0n) {
|
|
47
|
+
throw new types_1.NegativeNativeAmountError(nativeAmount);
|
|
48
|
+
}
|
|
49
|
+
if (!(0, morpho_ts_1.isDefined)(wNative)) {
|
|
50
|
+
throw new types_1.ChainWNativeMissingError(chainId);
|
|
51
|
+
}
|
|
52
|
+
if (!(0, viem_1.isAddressEqual)(asset, wNative)) {
|
|
53
|
+
throw new types_1.NativeAmountOnNonWNativeVaultError(asset, wNative);
|
|
54
|
+
}
|
|
55
|
+
actions.push(
|
|
56
|
+
// Transfers native token from Bundler3 to GeneralAdapter1 for wrapping.
|
|
57
|
+
{
|
|
58
|
+
type: "nativeTransfer",
|
|
59
|
+
args: [bundler3, generalAdapter1, nativeAmount, false /* skipRevert */],
|
|
60
|
+
}, {
|
|
61
|
+
type: "wrapNative",
|
|
62
|
+
args: [nativeAmount, generalAdapter1, false /* skipRevert */],
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
if (amount > 0n) {
|
|
66
|
+
if (requirementSignature) {
|
|
67
|
+
actions.push(...(0, getRequirementsAction_1.getRequirementsAction)({
|
|
68
|
+
chainId,
|
|
69
|
+
asset,
|
|
70
|
+
amount,
|
|
71
|
+
requirementSignature,
|
|
72
|
+
}));
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
actions.push({
|
|
76
|
+
type: "erc20TransferFrom",
|
|
77
|
+
args: [asset, amount, generalAdapter1, false /* skipRevert */],
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
const totalAssets = amount + (nativeAmount ?? 0n);
|
|
82
|
+
if (totalAssets === 0n) {
|
|
83
|
+
throw new types_1.ZeroDepositAmountError(vaultAddress);
|
|
84
|
+
}
|
|
85
|
+
actions.push({
|
|
86
|
+
type: "erc4626Deposit",
|
|
87
|
+
args: [
|
|
88
|
+
vaultAddress,
|
|
89
|
+
totalAssets,
|
|
90
|
+
maxSharePrice,
|
|
91
|
+
recipient,
|
|
92
|
+
false /* skipRevert */,
|
|
93
|
+
],
|
|
94
|
+
});
|
|
95
|
+
let tx = bundler_sdk_viem_1.BundlerAction.encodeBundle(chainId, actions);
|
|
96
|
+
if (nativeAmount) {
|
|
97
|
+
tx = { ...tx, value: nativeAmount };
|
|
98
|
+
}
|
|
99
|
+
if (metadata) {
|
|
100
|
+
tx = (0, helpers_1.addTransactionMetadata)(tx, metadata);
|
|
101
|
+
}
|
|
102
|
+
return (0, morpho_ts_1.deepFreeze)({
|
|
103
|
+
...tx,
|
|
104
|
+
action: {
|
|
105
|
+
type: "vaultV1Deposit",
|
|
106
|
+
args: {
|
|
107
|
+
vault: vaultAddress,
|
|
108
|
+
amount,
|
|
109
|
+
maxSharePrice,
|
|
110
|
+
recipient,
|
|
111
|
+
nativeAmount,
|
|
112
|
+
},
|
|
113
|
+
},
|
|
114
|
+
});
|
|
115
|
+
};
|
|
116
|
+
exports.vaultV1Deposit = vaultV1Deposit;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./deposit"), exports);
|
|
18
|
+
__exportStar(require("./redeem"), exports);
|
|
19
|
+
__exportStar(require("./withdraw"), exports);
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { type Address } from "viem";
|
|
2
|
+
import { type Metadata, type Transaction, type VaultV1RedeemAction } from "../../types";
|
|
3
|
+
export interface VaultV1RedeemParams {
|
|
4
|
+
vault: {
|
|
5
|
+
address: Address;
|
|
6
|
+
};
|
|
7
|
+
args: {
|
|
8
|
+
shares: bigint;
|
|
9
|
+
recipient: Address;
|
|
10
|
+
onBehalf: Address;
|
|
11
|
+
};
|
|
12
|
+
metadata?: Metadata;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Prepares a redeem transaction for a VaultV1 (MetaMorpho) contract.
|
|
16
|
+
*
|
|
17
|
+
* Direct vault call — no bundler needed. Redeem has no inflation attack surface.
|
|
18
|
+
*
|
|
19
|
+
* @param {Object} params - The redeem parameters.
|
|
20
|
+
* @param {Object} params.vault - The vault identifiers.
|
|
21
|
+
* @param {Address} params.vault.address - The vault address.
|
|
22
|
+
* @param {Object} params.args - The redeem arguments.
|
|
23
|
+
* @param {bigint} params.args.shares - Amount of shares to redeem.
|
|
24
|
+
* @param {Address} params.args.recipient - Receives the redeemed assets.
|
|
25
|
+
* @param {Address} params.args.onBehalf - Address whose shares are burned.
|
|
26
|
+
* @param {Metadata} [params.metadata] - Optional analytics metadata.
|
|
27
|
+
* @returns {Readonly<Transaction<VaultV1RedeemAction>>} The prepared redeem transaction.
|
|
28
|
+
*/
|
|
29
|
+
export declare const vaultV1Redeem: ({ vault: { address: vaultAddress }, args: { shares, recipient, onBehalf }, metadata, }: VaultV1RedeemParams) => Readonly<Transaction<VaultV1RedeemAction>>;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.vaultV1Redeem = void 0;
|
|
4
|
+
const blue_sdk_viem_1 = require("@morpho-org/blue-sdk-viem");
|
|
5
|
+
const morpho_ts_1 = require("@morpho-org/morpho-ts");
|
|
6
|
+
const viem_1 = require("viem");
|
|
7
|
+
const helpers_1 = require("../../helpers");
|
|
8
|
+
const types_1 = require("../../types");
|
|
9
|
+
/**
|
|
10
|
+
* Prepares a redeem transaction for a VaultV1 (MetaMorpho) contract.
|
|
11
|
+
*
|
|
12
|
+
* Direct vault call — no bundler needed. Redeem has no inflation attack surface.
|
|
13
|
+
*
|
|
14
|
+
* @param {Object} params - The redeem parameters.
|
|
15
|
+
* @param {Object} params.vault - The vault identifiers.
|
|
16
|
+
* @param {Address} params.vault.address - The vault address.
|
|
17
|
+
* @param {Object} params.args - The redeem arguments.
|
|
18
|
+
* @param {bigint} params.args.shares - Amount of shares to redeem.
|
|
19
|
+
* @param {Address} params.args.recipient - Receives the redeemed assets.
|
|
20
|
+
* @param {Address} params.args.onBehalf - Address whose shares are burned.
|
|
21
|
+
* @param {Metadata} [params.metadata] - Optional analytics metadata.
|
|
22
|
+
* @returns {Readonly<Transaction<VaultV1RedeemAction>>} The prepared redeem transaction.
|
|
23
|
+
*/
|
|
24
|
+
const vaultV1Redeem = ({ vault: { address: vaultAddress }, args: { shares, recipient, onBehalf }, metadata, }) => {
|
|
25
|
+
if (shares <= 0n) {
|
|
26
|
+
throw new types_1.NonPositiveSharesAmountError(vaultAddress);
|
|
27
|
+
}
|
|
28
|
+
let tx = {
|
|
29
|
+
to: vaultAddress,
|
|
30
|
+
data: (0, viem_1.encodeFunctionData)({
|
|
31
|
+
abi: blue_sdk_viem_1.metaMorphoAbi,
|
|
32
|
+
functionName: "redeem",
|
|
33
|
+
args: [shares, recipient, onBehalf],
|
|
34
|
+
}),
|
|
35
|
+
value: 0n,
|
|
36
|
+
};
|
|
37
|
+
if (metadata) {
|
|
38
|
+
tx = (0, helpers_1.addTransactionMetadata)(tx, metadata);
|
|
39
|
+
}
|
|
40
|
+
return (0, morpho_ts_1.deepFreeze)({
|
|
41
|
+
...tx,
|
|
42
|
+
action: {
|
|
43
|
+
type: "vaultV1Redeem",
|
|
44
|
+
args: { vault: vaultAddress, shares, recipient },
|
|
45
|
+
},
|
|
46
|
+
});
|
|
47
|
+
};
|
|
48
|
+
exports.vaultV1Redeem = vaultV1Redeem;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { type Address } from "viem";
|
|
2
|
+
import { type Metadata, type Transaction, type VaultV1WithdrawAction } from "../../types";
|
|
3
|
+
export interface VaultV1WithdrawParams {
|
|
4
|
+
vault: {
|
|
5
|
+
address: Address;
|
|
6
|
+
};
|
|
7
|
+
args: {
|
|
8
|
+
amount: bigint;
|
|
9
|
+
recipient: Address;
|
|
10
|
+
onBehalf: Address;
|
|
11
|
+
};
|
|
12
|
+
metadata?: Metadata;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Prepares a withdraw transaction for a VaultV1 (MetaMorpho) contract.
|
|
16
|
+
*
|
|
17
|
+
* Direct vault call — no bundler needed. Withdraw has no inflation attack surface.
|
|
18
|
+
*
|
|
19
|
+
* @param {Object} params - The withdraw parameters.
|
|
20
|
+
* @param {Object} params.vault - The vault identifiers.
|
|
21
|
+
* @param {Address} params.vault.address - The vault address.
|
|
22
|
+
* @param {Object} params.args - The withdraw arguments.
|
|
23
|
+
* @param {bigint} params.args.amount - Amount of assets to withdraw.
|
|
24
|
+
* @param {Address} params.args.recipient - Receives the withdrawn assets.
|
|
25
|
+
* @param {Address} params.args.onBehalf - Address whose shares are burned.
|
|
26
|
+
* @param {Metadata} [params.metadata] - Optional analytics metadata.
|
|
27
|
+
* @returns {Readonly<Transaction<VaultV1WithdrawAction>>} The prepared withdraw transaction.
|
|
28
|
+
*/
|
|
29
|
+
export declare const vaultV1Withdraw: ({ vault: { address: vaultAddress }, args: { amount, recipient, onBehalf }, metadata, }: VaultV1WithdrawParams) => Readonly<Transaction<VaultV1WithdrawAction>>;
|