@zebec-network/zebec-vault-sdk 5.2.0 → 5.2.2
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 +294 -215
- package/dist/constants.d.ts +0 -4
- package/dist/constants.js +1 -11
- package/dist/errors.d.ts +0 -3
- package/dist/errors.js +3 -20
- package/dist/providers.d.ts +2 -2
- package/dist/service.d.ts +1 -1
- package/dist/service.js +19 -20
- package/package.json +50 -50
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
A Typescript SDK for interacting with Zebec Vault on Solana, enabling secure multi operations, token streaming, staking, and virtual card management.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
## **Features**
|
|
6
6
|
|
|
7
7
|
- **Vault Management**: Create and manage secure vaults with proposal-based execution
|
|
8
8
|
- **Token Operations**: Deposit and withdraw SOL and SPL tokens
|
|
@@ -11,7 +11,7 @@ A Typescript SDK for interacting with Zebec Vault on Solana, enabling secure mul
|
|
|
11
11
|
- **Virtual Cards**: Create and load Zebec cards with automatic token swapping
|
|
12
12
|
- **Jupiter Integration**: Built-in token swapping for card operations
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
## **Installation**
|
|
15
15
|
|
|
16
16
|
```jsx
|
|
17
17
|
npm install @zebec-network/zebec-vault-sdk
|
|
@@ -21,23 +21,22 @@ npm install @zebec-network/zebec-vault-sdk
|
|
|
21
21
|
yarn add @zebec-network/zebec-vault-sdk
|
|
22
22
|
```
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
## **Quick Start**
|
|
25
25
|
|
|
26
|
-
|
|
26
|
+
### **Setup**
|
|
27
27
|
|
|
28
28
|
```tsx
|
|
29
29
|
import { Connection, Keypair } from "@solana/web3.js";
|
|
30
30
|
import { createAnchorProvider, ZebecVaultService } from "@zebec-network/zebec-vault-sdk";
|
|
31
31
|
|
|
32
32
|
// Create connection
|
|
33
|
-
const connection = new Connection("https://api.mainnet-beta.solana.com"); // use private
|
|
33
|
+
const connection = new Connection("https://api.mainnet-beta.solana.com"); // use a private dedicated RPC for production
|
|
34
34
|
|
|
35
35
|
// Create wallet adapter
|
|
36
|
-
//
|
|
37
|
-
// for example:
|
|
36
|
+
// For a frontend application, use the wallet provided by the wallet adapter:
|
|
38
37
|
const wallet = useAnchorWallet();
|
|
39
38
|
|
|
40
|
-
//
|
|
39
|
+
// For a server-side app, use the Wallet class from @coral-xyz/anchor:
|
|
41
40
|
const wallet = new Wallet(keypair); // create keypair from secret key
|
|
42
41
|
|
|
43
42
|
// Create provider
|
|
@@ -51,29 +50,29 @@ const vaultService = ZebecVaultService.create(provider, "mainnet-beta");
|
|
|
51
50
|
|
|
52
51
|
### **Vault Operations**
|
|
53
52
|
|
|
54
|
-
Each user has a vault that is derived from
|
|
53
|
+
Each user has a vault that is derived from a seed containing the user's wallet. A vault signer is then derived from the vault as a seed. The vault signer holds SPL token and SOL balances and signs transactions during CPI executions.
|
|
55
54
|
|
|
56
|
-
|
|
55
|
+
#### Create a vault
|
|
57
56
|
|
|
58
|
-
```
|
|
57
|
+
```tsx
|
|
59
58
|
const payload = await vaultService.createVault({
|
|
60
|
-
|
|
59
|
+
payer: wallet.publicKey, // optional if using AnchorProvider
|
|
61
60
|
});
|
|
62
61
|
|
|
63
62
|
const signature = await payload.execute();
|
|
64
63
|
console.log("Vault created:", signature);
|
|
65
64
|
```
|
|
66
65
|
|
|
67
|
-
|
|
66
|
+
#### Get Vault Information
|
|
68
67
|
|
|
69
68
|
```tsx
|
|
70
|
-
// Get specific user's vault
|
|
69
|
+
// Get a specific user's vault (param is optional when using AnchorProvider)
|
|
71
70
|
const vaultInfo = await vaultService.getVaultInfoOfUser(userAddress);
|
|
72
71
|
|
|
73
72
|
if (vaultInfo) {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
73
|
+
console.log("Vault:", vaultInfo.vault.toString());
|
|
74
|
+
console.log("Owner:", vaultInfo.owner.toString());
|
|
75
|
+
console.log("Created:", new Date(vaultInfo.createdDate * 1000));
|
|
77
76
|
}
|
|
78
77
|
|
|
79
78
|
// Get all vaults
|
|
@@ -81,101 +80,102 @@ const allVaults = await vaultService.getAllVaultsInfo();
|
|
|
81
80
|
console.log(`Total vaults: ${allVaults.length}`);
|
|
82
81
|
```
|
|
83
82
|
|
|
84
|
-
|
|
83
|
+
#### Deposit SOL
|
|
85
84
|
|
|
86
85
|
```tsx
|
|
87
86
|
const payload = await vaultService.depositSol({
|
|
88
|
-
|
|
89
|
-
|
|
87
|
+
depositor: wallet.publicKey,
|
|
88
|
+
amount: 1.5, // SOL amount
|
|
90
89
|
});
|
|
90
|
+
|
|
91
|
+
const signature = await payload.execute();
|
|
91
92
|
```
|
|
92
93
|
|
|
93
|
-
|
|
94
|
+
#### Deposit SPL Tokens
|
|
94
95
|
|
|
95
96
|
```tsx
|
|
96
97
|
const payload = await vaultService.deposit({
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
98
|
+
depositor: wallet.publicKey,
|
|
99
|
+
tokenMint: "TOKEN_MINT_ADDRESS",
|
|
100
|
+
amount: 100, // token amount
|
|
100
101
|
});
|
|
101
102
|
|
|
102
103
|
const signature = await payload.execute();
|
|
103
104
|
```
|
|
104
105
|
|
|
105
|
-
> **_Note: If WSOL address is given
|
|
106
|
+
> **_Note: If the WSOL address is given as `tokenMint`, SOL will be wrapped to WSOL and deposited as an SPL token._**
|
|
106
107
|
|
|
107
|
-
|
|
108
|
+
#### Withdraw SOL
|
|
108
109
|
|
|
109
110
|
```tsx
|
|
110
111
|
const payload = await vaultService.withdrawSol({
|
|
111
|
-
|
|
112
|
-
|
|
112
|
+
withdrawer: wallet.publicKey,
|
|
113
|
+
amount: 0.5,
|
|
113
114
|
});
|
|
114
115
|
|
|
115
116
|
const signature = await payload.execute();
|
|
116
117
|
```
|
|
117
118
|
|
|
118
|
-
|
|
119
|
+
#### Withdraw SPL Tokens
|
|
119
120
|
|
|
120
121
|
```tsx
|
|
121
122
|
const payload = await vaultService.withdraw({
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
123
|
+
withdrawer: wallet.publicKey,
|
|
124
|
+
tokenMint: "TOKEN_MINT_ADDRESS",
|
|
125
|
+
amount: 50,
|
|
125
126
|
});
|
|
126
127
|
|
|
127
128
|
const signature = await payload.execute();
|
|
128
129
|
```
|
|
129
130
|
|
|
130
|
-
> **_Note: If WSOL
|
|
131
|
+
> **_Note: If the WSOL address is given as `tokenMint`, WSOL will be withdrawn and unwrapped into the withdrawer's wallet._**
|
|
131
132
|
|
|
132
133
|
### Proposal System
|
|
133
134
|
|
|
134
|
-
Proposal System includes methods
|
|
135
|
+
The Proposal System includes methods for creating proposals, appending actions, and executing proposals. A proposal is like a Solana transaction but with extra fields such as proposal stage, created date, expiry date, execution status, and name. Each proposal contains one or more `ProposalAction`, which is similar to a `TransactionInstruction` in Solana. During execution, proposal actions run in order. You can delete a proposal to reclaim the SOL rent used to create it. Each proposal belongs to a vault and only the vault signer can execute, delete, or append actions to it.
|
|
135
136
|
|
|
136
|
-
|
|
137
|
+
#### Create a Proposal
|
|
137
138
|
|
|
138
139
|
```tsx
|
|
139
|
-
import { SystemProgram
|
|
140
|
+
import { SystemProgram } from "@solana/web3.js";
|
|
140
141
|
import { parseSol } from "@zebec-network/solana-common";
|
|
142
|
+
import { deriveUserVault, deriveVaultSigner } from "@zebec-network/zebec-vault-sdk";
|
|
141
143
|
|
|
142
|
-
const [vault] = deriveUserVault(wallet.publicKey,
|
|
143
|
-
const [vaultSigner] = deriveVaultSigner(vault,
|
|
144
|
+
const [vault] = deriveUserVault(wallet.publicKey, vaultService.vaultV1ProgramId);
|
|
145
|
+
const [vaultSigner] = deriveVaultSigner(vault, vaultService.vaultV1ProgramId);
|
|
144
146
|
const recipient = "<Recipient PublicKey>";
|
|
145
147
|
|
|
146
148
|
// Create custom instructions. For example:
|
|
147
149
|
const instruction = SystemProgram.transfer({
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
150
|
+
fromPubkey: vaultSigner,
|
|
151
|
+
toPubkey: recipient,
|
|
152
|
+
lamports: Number(parseSol(1)),
|
|
151
153
|
});
|
|
152
154
|
|
|
153
|
-
const proposalKeypair = Keypair.generate();
|
|
154
|
-
console.log("Proposal:", proposalKeypair.publicKey.toString());
|
|
155
|
-
|
|
156
155
|
const payload = await vaultService.createProposal({
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
156
|
+
proposer: wallet.publicKey,
|
|
157
|
+
name: "Transfer SOL",
|
|
158
|
+
actions: [instruction],
|
|
159
|
+
// proposalKeypair: Keypair.generate(), // optional; auto-generated if omitted
|
|
160
160
|
});
|
|
161
161
|
|
|
162
162
|
const signature = await payload.execute();
|
|
163
163
|
```
|
|
164
164
|
|
|
165
|
-
|
|
165
|
+
#### Get Proposals
|
|
166
166
|
|
|
167
167
|
```tsx
|
|
168
168
|
const proposals = await vaultService.getProposalsInfoOfVault(vaultAddress);
|
|
169
169
|
|
|
170
170
|
proposals.forEach((proposal) => {
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
171
|
+
console.log("Proposal:", proposal.name);
|
|
172
|
+
console.log("Status:", proposal.proposalStage);
|
|
173
|
+
console.log("Actions:", proposal.actions.length);
|
|
174
|
+
console.log("Executed:", proposal.isExecuted);
|
|
175
175
|
});
|
|
176
176
|
```
|
|
177
177
|
|
|
178
|
-
|
|
178
|
+
#### Append Actions
|
|
179
179
|
|
|
180
180
|
```tsx
|
|
181
181
|
import { SystemProgram } from "@solana/web3.js";
|
|
@@ -184,66 +184,71 @@ import { parseSol } from "@zebec-network/solana-common";
|
|
|
184
184
|
const proposal = "<Proposal PublicKey>";
|
|
185
185
|
|
|
186
186
|
const instruction = SystemProgram.transfer({
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
187
|
+
fromPubkey: vaultSigner,
|
|
188
|
+
toPubkey: wallet.publicKey,
|
|
189
|
+
lamports: Number(parseSol(0.01)),
|
|
190
190
|
});
|
|
191
191
|
|
|
192
|
-
const payload = await
|
|
193
|
-
|
|
194
|
-
|
|
192
|
+
const payload = await vaultService.appendActions({
|
|
193
|
+
proposal,
|
|
194
|
+
actions: [instruction],
|
|
195
195
|
});
|
|
196
196
|
|
|
197
197
|
const signature = await payload.execute();
|
|
198
198
|
```
|
|
199
199
|
|
|
200
|
-
|
|
200
|
+
#### Delete Proposal
|
|
201
201
|
|
|
202
202
|
```tsx
|
|
203
203
|
const proposal = "<Proposal PublicKey>";
|
|
204
|
-
const payload = await
|
|
204
|
+
const payload = await vaultService.deleteProposal({ proposal });
|
|
205
205
|
const deleteProposalSignature = await payload.execute();
|
|
206
206
|
```
|
|
207
207
|
|
|
208
|
-
|
|
208
|
+
#### Execute a Proposal
|
|
209
209
|
|
|
210
210
|
```tsx
|
|
211
211
|
const proposal = "<Proposal PublicKey>";
|
|
212
212
|
const lookupTableAddress = "<Lookup Table Address PublicKey>";
|
|
213
213
|
|
|
214
214
|
const payload = await vaultService.executeProposal({
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
215
|
+
caller: wallet.publicKey,
|
|
216
|
+
proposal,
|
|
217
|
+
addressLookupTables: [lookupTableAddress], // optional
|
|
218
218
|
});
|
|
219
219
|
|
|
220
220
|
const signature = await payload.execute();
|
|
221
221
|
```
|
|
222
222
|
|
|
223
|
-
|
|
224
|
-
|
|
223
|
+
#### Execute Proposal Directly (Single Transaction)
|
|
224
|
+
|
|
225
|
+
Proposal actions can be executed directly without creating a persistent proposal. However, this may hit the transaction size limit; some cases can be mitigated using address lookup tables.
|
|
225
226
|
|
|
226
227
|
```tsx
|
|
227
|
-
|
|
228
|
-
|
|
228
|
+
import { SystemProgram, TransactionInstruction } from "@solana/web3.js";
|
|
229
|
+
import { parseSol } from "@zebec-network/solana-common";
|
|
230
|
+
import { deriveUserVault, deriveVaultSigner } from "@zebec-network/zebec-vault-sdk";
|
|
231
|
+
|
|
232
|
+
const [vault] = deriveUserVault(wallet.publicKey, vaultService.vaultV1ProgramId);
|
|
233
|
+
const [vaultSigner] = deriveVaultSigner(vault, vaultService.vaultV1ProgramId);
|
|
229
234
|
const recipient = "<Recipient PublicKey>";
|
|
230
235
|
|
|
231
236
|
const instruction1 = SystemProgram.transfer({
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
237
|
+
fromPubkey: vaultSigner,
|
|
238
|
+
toPubkey: recipient,
|
|
239
|
+
lamports: Number(parseSol(1)),
|
|
235
240
|
});
|
|
236
241
|
|
|
237
242
|
const instruction2 = new TransactionInstruction({
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
243
|
+
keys: [],
|
|
244
|
+
programId: MEMO_PROGRAM_ID,
|
|
245
|
+
data: Buffer.from("Transfer 1 sol from vault signer to recipient", "utf8"),
|
|
241
246
|
});
|
|
242
247
|
|
|
243
248
|
const payload = await vaultService.executeProposalDirect({
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
249
|
+
proposer: wallet.publicKey,
|
|
250
|
+
actions: [instruction1, instruction2],
|
|
251
|
+
addressLookupTables: [lookupTableAddress],
|
|
247
252
|
});
|
|
248
253
|
|
|
249
254
|
const signature = await payload.execute();
|
|
@@ -251,80 +256,104 @@ const signature = await payload.execute();
|
|
|
251
256
|
|
|
252
257
|
### **Payment Streaming**
|
|
253
258
|
|
|
254
|
-
|
|
259
|
+
#### Create a Stream
|
|
255
260
|
|
|
256
261
|
```tsx
|
|
257
262
|
const payload = await vaultService.createStreamFromVault({
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
263
|
+
vaultOwner: wallet.publicKey,
|
|
264
|
+
receiver: recipientAddress,
|
|
265
|
+
streamToken: tokenMintAddress,
|
|
266
|
+
streamConfigName: "Config-001", // name of the stream configuration to use
|
|
267
|
+
amount: 1000, // total amount
|
|
268
|
+
duration: 2592000, // 30 days in seconds
|
|
269
|
+
startNow: true,
|
|
270
|
+
startTime: Math.floor(Date.now() / 1000),
|
|
271
|
+
automaticWithdrawal: false,
|
|
272
|
+
cancelableByRecipient: true,
|
|
273
|
+
cancelableBySender: true,
|
|
274
|
+
isPausable: true,
|
|
275
|
+
transferableByRecipient: false,
|
|
276
|
+
transferableBySender: false,
|
|
277
|
+
canTopup: true,
|
|
278
|
+
rateUpdatable: false,
|
|
279
|
+
cliffPercentage: 0, // 0-100
|
|
280
|
+
autoWithdrawFrequency: 86400, // 1 day in seconds; required when automaticWithdrawal is true
|
|
281
|
+
streamName: "Monthly Payment",
|
|
276
282
|
});
|
|
277
283
|
|
|
278
|
-
const await payload.execute();
|
|
284
|
+
const signature = await payload.execute();
|
|
279
285
|
```
|
|
280
286
|
|
|
281
|
-
|
|
287
|
+
#### Create Multiple Streams
|
|
282
288
|
|
|
283
|
-
There is a difference in payload
|
|
289
|
+
There is a difference in the payload returned for creating multiple streams. While other payloads are instances of `TransactionPayload`, the payload returned for multiple streams is an instance of `MultiTransactionPayload`. After calling `execute()`, it returns `MultiTransactionPayloadExecuteReturn`, which is an array of settled promise results — each containing either a transaction signature on success or a failure reason.
|
|
284
290
|
|
|
285
291
|
```tsx
|
|
286
292
|
export type MultiTransactionPayloadExecuteReturn = (PromiseSettledResult<string> & {
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
293
|
+
transactionData: {
|
|
294
|
+
readonly instructions: web3.TransactionInstruction[];
|
|
295
|
+
readonly feePayer: web3.PublicKey;
|
|
296
|
+
readonly signers?: web3.Signer[];
|
|
297
|
+
readonly addressLookupTableAccounts?: web3.AddressLookupTableAccount[];
|
|
298
|
+
};
|
|
299
|
+
transaction: web3.VersionedTransaction;
|
|
294
300
|
})[];
|
|
295
301
|
```
|
|
296
302
|
|
|
297
303
|
```tsx
|
|
298
304
|
const payload = await vaultService.createMultipleStreamFromVault({
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
305
|
+
vaultOwner: wallet.publicKey,
|
|
306
|
+
streamConfigName: "Config-001", // applies to all streams
|
|
307
|
+
streamInfo: [
|
|
308
|
+
{
|
|
309
|
+
receiver: recipient1,
|
|
310
|
+
streamToken: tokenMint,
|
|
311
|
+
amount: 500,
|
|
312
|
+
duration: 2592000,
|
|
313
|
+
startNow: false,
|
|
314
|
+
startTime: Math.floor(Date.now() / 1000) + 30,
|
|
315
|
+
automaticWithdrawal: false,
|
|
316
|
+
cancelableByRecipient: false,
|
|
317
|
+
cancelableBySender: false,
|
|
318
|
+
isPausable: false,
|
|
319
|
+
transferableByRecipient: false,
|
|
320
|
+
transferableBySender: false,
|
|
321
|
+
canTopup: false,
|
|
322
|
+
rateUpdatable: false,
|
|
323
|
+
cliffPercentage: 0,
|
|
324
|
+
streamName: "Stream 1",
|
|
325
|
+
},
|
|
326
|
+
{
|
|
327
|
+
receiver: recipient2,
|
|
328
|
+
streamToken: tokenMint,
|
|
329
|
+
amount: 1000,
|
|
330
|
+
duration: 2592000,
|
|
331
|
+
startNow: false,
|
|
332
|
+
startTime: Math.floor(Date.now() / 1000) + 30,
|
|
333
|
+
automaticWithdrawal: false,
|
|
334
|
+
cancelableByRecipient: false,
|
|
335
|
+
cancelableBySender: false,
|
|
336
|
+
isPausable: false,
|
|
337
|
+
transferableByRecipient: false,
|
|
338
|
+
transferableBySender: false,
|
|
339
|
+
canTopup: false,
|
|
340
|
+
rateUpdatable: false,
|
|
341
|
+
cliffPercentage: 0,
|
|
342
|
+
streamName: "Stream 2",
|
|
343
|
+
},
|
|
344
|
+
],
|
|
316
345
|
});
|
|
317
346
|
|
|
318
|
-
// Execute all streams in
|
|
319
|
-
const
|
|
347
|
+
// Execute all streams in separate transactions
|
|
348
|
+
const results = await payload.execute();
|
|
320
349
|
```
|
|
321
350
|
|
|
322
351
|
### **Pause/Resume a Stream**
|
|
323
352
|
|
|
324
353
|
```tsx
|
|
325
354
|
const payload = await vaultService.pauseResumeStream({
|
|
326
|
-
|
|
327
|
-
|
|
355
|
+
vaultOwner: wallet.publicKey,
|
|
356
|
+
streamMetadata: streamAddress,
|
|
328
357
|
});
|
|
329
358
|
|
|
330
359
|
const signature = await payload.execute();
|
|
@@ -334,8 +363,8 @@ const signature = await payload.execute();
|
|
|
334
363
|
|
|
335
364
|
```tsx
|
|
336
365
|
const payload = await vaultService.cancelStream({
|
|
337
|
-
|
|
338
|
-
|
|
366
|
+
vaultOwner: wallet.publicKey,
|
|
367
|
+
streamMetadata: streamAddress,
|
|
339
368
|
});
|
|
340
369
|
|
|
341
370
|
await payload.execute();
|
|
@@ -345,8 +374,8 @@ await payload.execute();
|
|
|
345
374
|
|
|
346
375
|
```tsx
|
|
347
376
|
const payload = await vaultService.withdrawStream({
|
|
348
|
-
|
|
349
|
-
|
|
377
|
+
vaultOwner: wallet.publicKey,
|
|
378
|
+
streamMetadata: streamAddress,
|
|
350
379
|
});
|
|
351
380
|
|
|
352
381
|
await payload.execute();
|
|
@@ -356,9 +385,9 @@ await payload.execute();
|
|
|
356
385
|
|
|
357
386
|
```tsx
|
|
358
387
|
const payload = await vaultService.changeStreamReceiver({
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
388
|
+
vaultOwner: wallet.publicKey,
|
|
389
|
+
streamMetadata: streamAddress,
|
|
390
|
+
newRecipient: newRecipientAddress,
|
|
362
391
|
});
|
|
363
392
|
|
|
364
393
|
await payload.execute();
|
|
@@ -370,46 +399,46 @@ await payload.execute();
|
|
|
370
399
|
const streamInfo = await vaultService.getStreamMetadataInfo(streamAddress);
|
|
371
400
|
|
|
372
401
|
console.log("Stream details:", {
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
402
|
+
sender: streamInfo.parties.sender,
|
|
403
|
+
receiver: streamInfo.parties.receiver,
|
|
404
|
+
token: streamInfo.financials.streamToken,
|
|
405
|
+
deposited: streamInfo.financials.depositedAmount,
|
|
406
|
+
withdrawn: streamInfo.financials.withdrawnAmount,
|
|
407
|
+
startTime: new Date(streamInfo.schedule.startTime * 1000),
|
|
408
|
+
endTime: new Date(streamInfo.schedule.endTime * 1000),
|
|
409
|
+
isPaused: streamInfo.schedule.pausedTimestamp > 0,
|
|
381
410
|
});
|
|
382
411
|
```
|
|
383
412
|
|
|
384
413
|
### Staking
|
|
385
414
|
|
|
386
|
-
|
|
415
|
+
#### Stake Tokens
|
|
387
416
|
|
|
388
417
|
```tsx
|
|
389
418
|
const payload = await vaultService.stake({
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
419
|
+
lockupName: "main-lockup",
|
|
420
|
+
vaultOwner: wallet.publicKey,
|
|
421
|
+
amount: 1000,
|
|
422
|
+
lockPeriod: 7776000, // 90 days in seconds; must be one of the lockup's valid periods
|
|
423
|
+
nonce: 0n,
|
|
395
424
|
});
|
|
396
425
|
|
|
397
426
|
await payload.execute();
|
|
398
427
|
```
|
|
399
428
|
|
|
400
|
-
|
|
429
|
+
#### Unstake Tokens
|
|
401
430
|
|
|
402
431
|
```tsx
|
|
403
432
|
const payload = await vaultService.unstake({
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
433
|
+
lockupName: "main-lockup",
|
|
434
|
+
vaultOwner: wallet.publicKey,
|
|
435
|
+
nonce: 0n,
|
|
407
436
|
});
|
|
408
437
|
|
|
409
438
|
await payload.execute();
|
|
410
439
|
```
|
|
411
440
|
|
|
412
|
-
|
|
441
|
+
#### Get Stake Nonce Information
|
|
413
442
|
|
|
414
443
|
```tsx
|
|
415
444
|
const nonceInfo = await vaultService.getStakeUserNonceInfo("main-lockup", wallet.publicKey);
|
|
@@ -419,85 +448,94 @@ console.log("Current nonce:", nonceInfo ? nonceInfo.nonce : 0n);
|
|
|
419
448
|
|
|
420
449
|
### Zebec Cards
|
|
421
450
|
|
|
422
|
-
|
|
451
|
+
#### Create a Silver Card
|
|
423
452
|
|
|
424
453
|
```tsx
|
|
425
454
|
const nextIndex = await vaultService.getNextCardIndex();
|
|
426
455
|
|
|
427
456
|
const payload = await vaultService.createSilverCard({
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
457
|
+
vaultOwnerAddress: wallet.publicKey,
|
|
458
|
+
nextCardIndex: nextIndex,
|
|
459
|
+
amount: 100, // USDC amount
|
|
460
|
+
usdcAddress: USDC_MINT_ADDRESS,
|
|
461
|
+
emailHash: Buffer.from("your-32-byte-hash"), // must be exactly 32 bytes
|
|
462
|
+
currency: "USD",
|
|
434
463
|
});
|
|
435
464
|
|
|
436
465
|
await payload.execute();
|
|
437
466
|
```
|
|
438
467
|
|
|
439
|
-
|
|
468
|
+
#### Load a Carbon Card
|
|
440
469
|
|
|
441
470
|
```tsx
|
|
442
471
|
const nextIndex = await vaultService.getNextCardIndex();
|
|
443
472
|
|
|
444
473
|
const payload = await vaultService.loadCarbonCard({
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
474
|
+
vaultOwnerAddress: wallet.publicKey,
|
|
475
|
+
nextCardIndex: nextIndex,
|
|
476
|
+
amount: 50,
|
|
477
|
+
usdcAddress: USDC_MINT_ADDRESS,
|
|
478
|
+
emailHash: Buffer.from("your-32-byte-hash"), // must be exactly 32 bytes
|
|
479
|
+
currency: "USD",
|
|
480
|
+
reloadCardId: "CARD_ID",
|
|
452
481
|
});
|
|
453
482
|
|
|
454
483
|
await payload.execute();
|
|
455
484
|
```
|
|
456
485
|
|
|
457
|
-
|
|
486
|
+
#### Swap and Create Silver Card
|
|
458
487
|
|
|
459
488
|
```tsx
|
|
460
489
|
// First, get a Jupiter quote
|
|
490
|
+
const quoteParams = new URLSearchParams({
|
|
491
|
+
inputMint: inputMint,
|
|
492
|
+
outputMint: USDC_MINT_ADDRESS,
|
|
493
|
+
amount: parsedAmount, // in smallest units
|
|
494
|
+
slippageBps: "50",
|
|
495
|
+
swapMode: "ExactIn",
|
|
496
|
+
});
|
|
461
497
|
const quoteResponse = await fetch(
|
|
462
|
-
|
|
498
|
+
`https://lite-api.jup.ag/swap/v1/quote?${quoteParams}`,
|
|
463
499
|
);
|
|
464
500
|
const quoteInfo = await quoteResponse.json();
|
|
465
501
|
|
|
502
|
+
const nextIndex = await vaultService.getNextCardIndex();
|
|
503
|
+
|
|
466
504
|
const payload = await vaultService.swapAndCreateSilverCard({
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
505
|
+
vaultOwnerAddress: wallet.publicKey,
|
|
506
|
+
quoteInfo: quoteInfo,
|
|
507
|
+
nextCardCounter: nextIndex,
|
|
508
|
+
emailHash: Buffer.from("your-32-byte-hash"), // must be exactly 32 bytes
|
|
509
|
+
currency: "USD",
|
|
510
|
+
wrapAndUnwrapSol: true, // set to true when swapping SOL
|
|
473
511
|
});
|
|
474
512
|
|
|
475
513
|
await payload.execute();
|
|
476
514
|
```
|
|
477
515
|
|
|
478
|
-
|
|
516
|
+
#### Swap and Load Carbon Card
|
|
479
517
|
|
|
480
518
|
```tsx
|
|
481
519
|
const payload = await vaultService.swapAndLoadCarbonCard({
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
520
|
+
vaultOwnerAddress: wallet.publicKey,
|
|
521
|
+
quoteInfo: quoteInfo,
|
|
522
|
+
nextCardCounter: nextIndex,
|
|
523
|
+
emailHash: Buffer.from("your-32-byte-hash"), // must be exactly 32 bytes
|
|
524
|
+
currency: "USD",
|
|
525
|
+
reloadCardId: "CARD_ID",
|
|
526
|
+
wrapAndUnwrapSol: true,
|
|
489
527
|
});
|
|
490
528
|
|
|
491
529
|
await payload.execute();
|
|
492
530
|
```
|
|
493
531
|
|
|
494
|
-
|
|
532
|
+
#### Get Card Custom Token Fees
|
|
495
533
|
|
|
496
534
|
```tsx
|
|
497
535
|
const tokenFees = await vaultService.getCardCustomTokenFees();
|
|
498
536
|
|
|
499
537
|
tokenFees.forEach((fee) => {
|
|
500
|
-
|
|
538
|
+
console.log(`Token: ${fee.tokenAddress}, Fee: ${fee.fee}%`);
|
|
501
539
|
});
|
|
502
540
|
```
|
|
503
541
|
|
|
@@ -518,15 +556,12 @@ const vaultInfo = await service.getVaultInfoOfUser(someAddress);
|
|
|
518
556
|
|
|
519
557
|
### **Advanced Features**
|
|
520
558
|
|
|
521
|
-
|
|
559
|
+
#### Program Derived Addresses (PDAs)
|
|
522
560
|
|
|
523
561
|
```tsx
|
|
524
562
|
import {
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
deriveStreamConfigPda,
|
|
528
|
-
deriveCardConfigPda,
|
|
529
|
-
deriveLockupAddress,
|
|
563
|
+
deriveUserVault,
|
|
564
|
+
deriveVaultSigner,
|
|
530
565
|
} from "@zebec-network/zebec-vault-sdk";
|
|
531
566
|
|
|
532
567
|
const [vaultAddress, vaultBump] = deriveUserVault(userAddress, vaultProgramId);
|
|
@@ -534,19 +569,19 @@ const [vaultAddress, vaultBump] = deriveUserVault(userAddress, vaultProgramId);
|
|
|
534
569
|
const [signerAddress, signerBump] = deriveVaultSigner(vaultAddress, vaultProgramId);
|
|
535
570
|
```
|
|
536
571
|
|
|
537
|
-
|
|
572
|
+
#### Transaction Utilities
|
|
538
573
|
|
|
539
574
|
```tsx
|
|
540
575
|
import { calculateProposalSize, transactionInstructionToProposalAction } from "@zebec-network/zebec-vault-sdk";
|
|
541
576
|
|
|
542
|
-
// Calculate proposal size
|
|
577
|
+
// Calculate proposal size (in bytes)
|
|
543
578
|
const size = calculateProposalSize("proposal-name", actions);
|
|
544
579
|
|
|
545
|
-
// Convert
|
|
580
|
+
// Convert a TransactionInstruction to a ProposalAction
|
|
546
581
|
const action = transactionInstructionToProposalAction(instruction);
|
|
547
582
|
```
|
|
548
583
|
|
|
549
|
-
|
|
584
|
+
#### Network Configuration
|
|
550
585
|
|
|
551
586
|
```tsx
|
|
552
587
|
// Mainnet
|
|
@@ -560,37 +595,81 @@ const devnetService = ZebecVaultService.create(provider, "devnet");
|
|
|
560
595
|
|
|
561
596
|
```tsx
|
|
562
597
|
import {
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
598
|
+
ZEBEC_VAULT_PROGRAM_ID,
|
|
599
|
+
JUPITER_AGGREGATOR_PROGRAM_ID,
|
|
600
|
+
CARD_LOOKUP_TABLE_ADDRESS,
|
|
601
|
+
STAKE_LOOKUP_TABLE_ADDRESS,
|
|
567
602
|
} from "@zebec-network/zebec-vault-sdk";
|
|
568
603
|
|
|
569
604
|
console.log("Vault Program:", ZEBEC_VAULT_PROGRAM_ID["mainnet-beta"]);
|
|
570
605
|
```
|
|
571
606
|
|
|
607
|
+
### **Error Types**
|
|
608
|
+
|
|
609
|
+
The SDK throws typed errors you can catch and inspect:
|
|
610
|
+
|
|
611
|
+
```tsx
|
|
612
|
+
import {
|
|
613
|
+
AmountOutOfRangeError,
|
|
614
|
+
DailyCardLimitReachedError,
|
|
615
|
+
InvalidUsdcAddressError,
|
|
616
|
+
NotEnoughBalanceError,
|
|
617
|
+
QuoteResponseError,
|
|
618
|
+
AssociatedTokenAccountDoesNotExistsError,
|
|
619
|
+
} from "@zebec-network/zebec-vault-sdk";
|
|
620
|
+
|
|
621
|
+
try {
|
|
622
|
+
await payload.execute();
|
|
623
|
+
} catch (err) {
|
|
624
|
+
if (err instanceof AmountOutOfRangeError) {
|
|
625
|
+
console.error(`Amount must be between ${err.minRange} and ${err.maxRange}`);
|
|
626
|
+
} else if (err instanceof DailyCardLimitReachedError) {
|
|
627
|
+
console.error(`Daily limit: ${err.dailyCardLimit}, requested: ${err.requestedAmount}`);
|
|
628
|
+
} else if (err instanceof NotEnoughBalanceError) {
|
|
629
|
+
console.error("Insufficient balance");
|
|
630
|
+
} else if (err instanceof AssociatedTokenAccountDoesNotExistsError) {
|
|
631
|
+
console.error("Token account does not exist");
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
```
|
|
635
|
+
|
|
572
636
|
### **Types**
|
|
573
637
|
|
|
574
638
|
The SDK exports comprehensive TypeScript types:
|
|
575
639
|
|
|
576
640
|
```tsx
|
|
577
641
|
import type {
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
642
|
+
VaultInfo,
|
|
643
|
+
ProposalInfo,
|
|
644
|
+
ProposalAction,
|
|
645
|
+
ProposalStage,
|
|
646
|
+
CreateStreamFromVaultParams,
|
|
647
|
+
createMultipleStreamFromVaultParams,
|
|
648
|
+
StreamMetadataInfo,
|
|
649
|
+
TokenFeeRecord,
|
|
650
|
+
QuoteInfo,
|
|
651
|
+
RouteInfo,
|
|
652
|
+
StakeUserNonceInfo,
|
|
653
|
+
CreateSilverCardParams,
|
|
654
|
+
LoadCarbonCardParams,
|
|
655
|
+
SwapAndCreateSilverCardParams,
|
|
656
|
+
SwapAndLoadCarbonCardParams,
|
|
657
|
+
CancelStreamParams,
|
|
658
|
+
PauseResumeStreamParams,
|
|
659
|
+
ChangeStreamReceiverParams,
|
|
660
|
+
WithdrawStreamParams,
|
|
661
|
+
ParsedCardConfigInfo,
|
|
662
|
+
WhitelistInfo,
|
|
663
|
+
Numeric,
|
|
586
664
|
} from "@zebec-network/zebec-vault-sdk";
|
|
587
665
|
```
|
|
588
666
|
|
|
589
667
|
## **Best Practices**
|
|
590
668
|
|
|
591
|
-
1. **Always check balances**
|
|
592
|
-
2. **Use proposals**
|
|
593
|
-
3. **Handle errors**
|
|
594
|
-
4. **Verify stream parameters**
|
|
595
|
-
5. **Test on `devnet`**
|
|
596
|
-
6. **Use address lookup tables**
|
|
669
|
+
1. **Always check balances** before operations
|
|
670
|
+
2. **Use proposals** for critical operations that require multiple instructions and cannot be executed in a single transaction
|
|
671
|
+
3. **Handle errors** appropriately with the provided error types
|
|
672
|
+
4. **Verify stream parameters** before creation (duration, amounts, permissions)
|
|
673
|
+
5. **Test on `devnet`** before deploying to `mainnet`
|
|
674
|
+
6. **Use address lookup tables** for complex transactions to reduce transaction size
|
|
675
|
+
7. **Use a private dedicated RPC** for production workloads
|
package/dist/constants.d.ts
CHANGED
|
@@ -1,6 +1,2 @@
|
|
|
1
1
|
export type RpcNetwork = "mainnet-beta" | "devnet";
|
|
2
2
|
export declare const ZEBEC_VAULT_PROGRAM_ID: Record<RpcNetwork, string>;
|
|
3
|
-
export declare const JUPITER_AGGREGATOR_PROGRAM_ID = "JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4";
|
|
4
|
-
export declare const CARD_LOOKUP_TABLE_ADDRESS: Record<RpcNetwork, string>;
|
|
5
|
-
export declare const JUPITER_SWAP_API = "https://lite-api.jup.ag/swap/v1/swap";
|
|
6
|
-
export declare const STAKE_LOOKUP_TABLE_ADDRESS: Record<RpcNetwork, string>;
|
package/dist/constants.js
CHANGED
|
@@ -1,17 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.ZEBEC_VAULT_PROGRAM_ID = void 0;
|
|
4
4
|
exports.ZEBEC_VAULT_PROGRAM_ID = {
|
|
5
5
|
"mainnet-beta": "zVLTdc9GmsZ6zjS6bdSFWh7p3BdiPPyju9y82Cr7Vs3",
|
|
6
6
|
devnet: "zVLTdc9GmsZ6zjS6bdSFWh7p3BdiPPyju9y82Cr7Vs3",
|
|
7
7
|
};
|
|
8
|
-
exports.JUPITER_AGGREGATOR_PROGRAM_ID = "JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4";
|
|
9
|
-
exports.CARD_LOOKUP_TABLE_ADDRESS = {
|
|
10
|
-
"mainnet-beta": "9BSK7XgPgAZJK6BEdiFDV8WKGye31uffvGjhQ1Zxob7F",
|
|
11
|
-
devnet: "CgPARkLEbygMJ8C9Z1u6MP57gvdnUERCxdhmR9bTFUSJ",
|
|
12
|
-
};
|
|
13
|
-
exports.JUPITER_SWAP_API = "https://lite-api.jup.ag/swap/v1/swap";
|
|
14
|
-
exports.STAKE_LOOKUP_TABLE_ADDRESS = {
|
|
15
|
-
"mainnet-beta": "EoKjJejKr4XsBdtUuYwzZcYd6tpGNijxCGgQocxtxQ8t",
|
|
16
|
-
devnet: "C4R2sL6yj7bzKfbdfwCfH68DZZ3QnzdmedE9wQqTfAAA",
|
|
17
|
-
};
|
package/dist/errors.d.ts
CHANGED
|
@@ -18,13 +18,10 @@ export declare class InvalidUsdcAddressError extends Error {
|
|
|
18
18
|
}
|
|
19
19
|
export declare class NotEnoughBalanceError extends Error {
|
|
20
20
|
name: string;
|
|
21
|
-
constructor(message: string);
|
|
22
21
|
}
|
|
23
22
|
export declare class QuoteResponseError extends Error {
|
|
24
23
|
name: string;
|
|
25
|
-
constructor(message: string);
|
|
26
24
|
}
|
|
27
25
|
export declare class AssociatedTokenAccountDoesNotExistsError extends Error {
|
|
28
26
|
name: string;
|
|
29
|
-
constructor(message: string);
|
|
30
27
|
}
|
package/dist/errors.js
CHANGED
|
@@ -7,12 +7,7 @@ class AmountOutOfRangeError extends Error {
|
|
|
7
7
|
value;
|
|
8
8
|
name = "AmountOutOfRangeError";
|
|
9
9
|
constructor(minRange, maxRange, value) {
|
|
10
|
-
super(
|
|
11
|
-
value +
|
|
12
|
-
"; Must be within " +
|
|
13
|
-
minRange +
|
|
14
|
-
"-" +
|
|
15
|
-
maxRange);
|
|
10
|
+
super(`Amount out of range: ${value}; Must be within ${minRange}-${maxRange}`);
|
|
16
11
|
this.minRange = minRange;
|
|
17
12
|
this.maxRange = maxRange;
|
|
18
13
|
this.value = value;
|
|
@@ -24,10 +19,7 @@ class DailyCardLimitReachedError extends Error {
|
|
|
24
19
|
requestedAmount;
|
|
25
20
|
name = "DailyCardLimitReachedError";
|
|
26
21
|
constructor(dailyCardLimit, requestedAmount) {
|
|
27
|
-
super(
|
|
28
|
-
dailyCardLimit +
|
|
29
|
-
" Requested: " +
|
|
30
|
-
requestedAmount);
|
|
22
|
+
super(`Daily card limit reached. Limit: ${dailyCardLimit} Requested: ${requestedAmount}`);
|
|
31
23
|
this.dailyCardLimit = dailyCardLimit;
|
|
32
24
|
this.requestedAmount = requestedAmount;
|
|
33
25
|
}
|
|
@@ -37,29 +29,20 @@ class InvalidUsdcAddressError extends Error {
|
|
|
37
29
|
mintAddress;
|
|
38
30
|
name = "InvalidUsdcAddressError";
|
|
39
31
|
constructor(mintAddress) {
|
|
40
|
-
super(
|
|
32
|
+
super(`Invalid USDC address: ${mintAddress}`);
|
|
41
33
|
this.mintAddress = mintAddress;
|
|
42
34
|
}
|
|
43
35
|
}
|
|
44
36
|
exports.InvalidUsdcAddressError = InvalidUsdcAddressError;
|
|
45
37
|
class NotEnoughBalanceError extends Error {
|
|
46
38
|
name = "NotEnoughBalanceError";
|
|
47
|
-
constructor(message) {
|
|
48
|
-
super(message);
|
|
49
|
-
}
|
|
50
39
|
}
|
|
51
40
|
exports.NotEnoughBalanceError = NotEnoughBalanceError;
|
|
52
41
|
class QuoteResponseError extends Error {
|
|
53
42
|
name = "QuoteResponseError";
|
|
54
|
-
constructor(message) {
|
|
55
|
-
super(message);
|
|
56
|
-
}
|
|
57
43
|
}
|
|
58
44
|
exports.QuoteResponseError = QuoteResponseError;
|
|
59
45
|
class AssociatedTokenAccountDoesNotExistsError extends Error {
|
|
60
46
|
name = "AssociatedTokenAccountDoesNotExistsError";
|
|
61
|
-
constructor(message) {
|
|
62
|
-
super(message);
|
|
63
|
-
}
|
|
64
47
|
}
|
|
65
48
|
exports.AssociatedTokenAccountDoesNotExistsError = AssociatedTokenAccountDoesNotExistsError;
|
package/dist/providers.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Address, AnchorProvider } from "@coral-xyz/anchor";
|
|
2
|
-
import { ConfirmOptions, Connection, PublicKey, Transaction, VersionedTransaction } from "@solana/web3.js";
|
|
1
|
+
import { type Address, AnchorProvider } from "@coral-xyz/anchor";
|
|
2
|
+
import type { ConfirmOptions, Connection, PublicKey, Transaction, VersionedTransaction } from "@solana/web3.js";
|
|
3
3
|
export declare class ReadonlyProvider {
|
|
4
4
|
readonly connection: Connection;
|
|
5
5
|
readonly walletAddress?: PublicKey;
|
package/dist/service.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ import { type ZebecCardV2Idl } from "@zebec-network/zebec-card-v2-sdk";
|
|
|
5
5
|
import { type ZebecStakeIdlV1 } from "@zebec-network/zebec-stake-sdk";
|
|
6
6
|
import { type ZebecStreamIdl } from "@zebec-network/zebec-stream-sdk";
|
|
7
7
|
import { type ZebecVaultV1Idl } from "./artifacts";
|
|
8
|
-
import {
|
|
8
|
+
import type { RpcNetwork } from "./constants";
|
|
9
9
|
import type { CancelStreamParams, ChangeStreamReceiverParams, CreateSilverCardInstructionData, CreateSilverCardParams, CreateStreamFromVaultParams, createMultipleStreamFromVaultParams, LoadCarbonCardInstructionData, LoadCarbonCardParams, Numeric, PauseResumeStreamParams, ProposalAction, ProposalInfo, StakeInstructionData, StakeUserNonceInfo, StreamMetadataInfo, SwapAndCreateSilverCardParams, SwapAndLoadCarbonCardParams, TokenFeeRecord, VaultInfo, WithdrawStreamParams } from "./types";
|
|
10
10
|
export declare class ZebecVaultService {
|
|
11
11
|
readonly provider: Provider;
|
package/dist/service.js
CHANGED
|
@@ -15,7 +15,6 @@ const zebec_stream_sdk_1 = require("@zebec-network/zebec-stream-sdk");
|
|
|
15
15
|
const assert_1 = __importDefault(require("assert"));
|
|
16
16
|
const bignumber_js_1 = require("bignumber.js");
|
|
17
17
|
const artifacts_1 = require("./artifacts");
|
|
18
|
-
const constants_1 = require("./constants");
|
|
19
18
|
const errors_1 = require("./errors");
|
|
20
19
|
const pda_1 = require("./pda");
|
|
21
20
|
const utils_1 = require("./utils");
|
|
@@ -652,7 +651,7 @@ class ZebecVaultService {
|
|
|
652
651
|
});
|
|
653
652
|
return acc;
|
|
654
653
|
}, []);
|
|
655
|
-
const lookupTables = await this.connection.getAddressLookupTable((0, anchor_1.translateAddress)(
|
|
654
|
+
const lookupTables = await this.connection.getAddressLookupTable((0, anchor_1.translateAddress)(zebec_card_v2_sdk_1.CARD_LOOKUP_TABLE_ADDRESS[this.network]));
|
|
656
655
|
const lookupTableAccount = lookupTables.value;
|
|
657
656
|
(0, assert_1.default)(lookupTableAccount, "Lookup table account not found");
|
|
658
657
|
const executeProposalDirectIx = await this.getExecuteProposalDirectInstruction(vaultOwner, actions, remainingAccounts);
|
|
@@ -706,7 +705,7 @@ class ZebecVaultService {
|
|
|
706
705
|
});
|
|
707
706
|
return acc;
|
|
708
707
|
}, []);
|
|
709
|
-
const lookupTables = await this.connection.getAddressLookupTable((0, anchor_1.translateAddress)(
|
|
708
|
+
const lookupTables = await this.connection.getAddressLookupTable((0, anchor_1.translateAddress)(zebec_card_v2_sdk_1.CARD_LOOKUP_TABLE_ADDRESS[this.network]));
|
|
710
709
|
const lookupTableAccount = lookupTables.value;
|
|
711
710
|
(0, assert_1.default)(lookupTableAccount, "Lookup table account not found");
|
|
712
711
|
const executeProposalDirectIx = await this.getExecuteProposalDirectInstruction(vaultOwner, actions, remainingAccounts);
|
|
@@ -765,7 +764,7 @@ class ZebecVaultService {
|
|
|
765
764
|
const amountAfterFeeDeduction = amount.minus(amount.times(swapFee.div(100)));
|
|
766
765
|
await this._checkAmountIsWithinProviderRange(cardConfigInfo, amountAfterFeeDeduction);
|
|
767
766
|
await this._checkAmountIsWithinDailyCardLimit(cardConfigInfo, userPurchaseRecord, amountAfterFeeDeduction);
|
|
768
|
-
const { swapTransaction } = await (await fetch(
|
|
767
|
+
const { swapTransaction } = await (await fetch(zebec_card_v2_sdk_1.JUPITER_SWAP_API, {
|
|
769
768
|
method: "POST",
|
|
770
769
|
headers: {
|
|
771
770
|
"Content-Type": "application/json",
|
|
@@ -790,7 +789,7 @@ class ZebecVaultService {
|
|
|
790
789
|
.getAccountInfo(lookup.accountKey)
|
|
791
790
|
.then((res) => {
|
|
792
791
|
if (!res) {
|
|
793
|
-
throw new Error(`Lookup table account not found for key: ${(0, anchor_1.translateAddress)(
|
|
792
|
+
throw new Error(`Lookup table account not found for key: ${(0, anchor_1.translateAddress)(zebec_card_v2_sdk_1.CARD_LOOKUP_TABLE_ADDRESS[this.network]).toString()}`);
|
|
794
793
|
}
|
|
795
794
|
return res.data;
|
|
796
795
|
});
|
|
@@ -800,15 +799,15 @@ class ZebecVaultService {
|
|
|
800
799
|
});
|
|
801
800
|
}));
|
|
802
801
|
const lookupTableData = await this.connection
|
|
803
|
-
.getAccountInfo((0, anchor_1.translateAddress)(
|
|
802
|
+
.getAccountInfo((0, anchor_1.translateAddress)(zebec_card_v2_sdk_1.CARD_LOOKUP_TABLE_ADDRESS[this.network]))
|
|
804
803
|
.then((res) => {
|
|
805
804
|
if (!res) {
|
|
806
|
-
throw new Error(`Lookup table account not found for key: ${(0, anchor_1.translateAddress)(
|
|
805
|
+
throw new Error(`Lookup table account not found for key: ${(0, anchor_1.translateAddress)(zebec_card_v2_sdk_1.CARD_LOOKUP_TABLE_ADDRESS[this.network]).toString()}`);
|
|
807
806
|
}
|
|
808
807
|
return res.data;
|
|
809
808
|
});
|
|
810
809
|
addressLookupTableAccounts.push(new web3_js_1.AddressLookupTableAccount({
|
|
811
|
-
key: (0, anchor_1.translateAddress)(
|
|
810
|
+
key: (0, anchor_1.translateAddress)(zebec_card_v2_sdk_1.CARD_LOOKUP_TABLE_ADDRESS[this.network]),
|
|
812
811
|
state: web3_js_1.AddressLookupTableAccount.deserialize(lookupTableData),
|
|
813
812
|
}));
|
|
814
813
|
// console.log("address lookup table:\n", addressLookupTableAccounts);
|
|
@@ -816,9 +815,9 @@ class ZebecVaultService {
|
|
|
816
815
|
const message = web3_js_1.TransactionMessage.decompile(transaction.message, {
|
|
817
816
|
addressLookupTableAccounts: addressLookupTableAccounts,
|
|
818
817
|
});
|
|
819
|
-
const swapInstruction = message.instructions.find((ix) => ix.programId.equals((0, anchor_1.translateAddress)(
|
|
818
|
+
const swapInstruction = message.instructions.find((ix) => ix.programId.equals((0, anchor_1.translateAddress)(zebec_card_v2_sdk_1.JUPITER_AGGREGATOR_PROGRAM_ID)));
|
|
820
819
|
(0, assert_1.default)(swapInstruction, "Swap instruction not found in the transaction message");
|
|
821
|
-
const otherIxs = message.instructions.filter((ix) => !ix.programId.equals((0, anchor_1.translateAddress)(
|
|
820
|
+
const otherIxs = message.instructions.filter((ix) => !ix.programId.equals((0, anchor_1.translateAddress)(zebec_card_v2_sdk_1.JUPITER_AGGREGATOR_PROGRAM_ID)) &&
|
|
822
821
|
!ix.programId.equals(web3_js_1.ComputeBudgetProgram.programId));
|
|
823
822
|
const index = new anchor_1.BN(params.nextCardCounter.toString());
|
|
824
823
|
const swapAndCreateSilverCardIx = await this.getSwapAndCreateSilverCardInstruction(vaultOwner, cardVault, cardVaultAta, revenueVault, revenueVaultAta, inputMint, usdc, vaultSigner, {
|
|
@@ -884,7 +883,7 @@ class ZebecVaultService {
|
|
|
884
883
|
const amountAfterFeeDeduction = amount.minus(amount.times(swapFee.div(100)));
|
|
885
884
|
await this._checkAmountIsWithinProviderRange(cardConfigInfo, amountAfterFeeDeduction);
|
|
886
885
|
await this._checkAmountIsWithinDailyCardLimit(cardConfigInfo, userPurchaseRecord, amountAfterFeeDeduction);
|
|
887
|
-
const { swapTransaction } = await (await fetch(
|
|
886
|
+
const { swapTransaction } = await (await fetch(zebec_card_v2_sdk_1.JUPITER_SWAP_API, {
|
|
888
887
|
method: "POST",
|
|
889
888
|
headers: {
|
|
890
889
|
"Content-Type": "application/json",
|
|
@@ -919,15 +918,15 @@ class ZebecVaultService {
|
|
|
919
918
|
});
|
|
920
919
|
}));
|
|
921
920
|
const lookupTableData = await this.connection
|
|
922
|
-
.getAccountInfo((0, anchor_1.translateAddress)(
|
|
921
|
+
.getAccountInfo((0, anchor_1.translateAddress)(zebec_card_v2_sdk_1.CARD_LOOKUP_TABLE_ADDRESS[this.network]))
|
|
923
922
|
.then((res) => {
|
|
924
923
|
if (!res) {
|
|
925
|
-
throw new Error(`Lookup table account not found for key: ${(0, anchor_1.translateAddress)(
|
|
924
|
+
throw new Error(`Lookup table account not found for key: ${(0, anchor_1.translateAddress)(zebec_card_v2_sdk_1.CARD_LOOKUP_TABLE_ADDRESS[this.network]).toString()}`);
|
|
926
925
|
}
|
|
927
926
|
return res.data;
|
|
928
927
|
});
|
|
929
928
|
addressLookupTableAccounts.push(new web3_js_1.AddressLookupTableAccount({
|
|
930
|
-
key: (0, anchor_1.translateAddress)(
|
|
929
|
+
key: (0, anchor_1.translateAddress)(zebec_card_v2_sdk_1.CARD_LOOKUP_TABLE_ADDRESS[this.network]),
|
|
931
930
|
state: web3_js_1.AddressLookupTableAccount.deserialize(lookupTableData),
|
|
932
931
|
}));
|
|
933
932
|
// console.log("address lookup table:\n", addressLookupTableAccounts);
|
|
@@ -935,9 +934,9 @@ class ZebecVaultService {
|
|
|
935
934
|
const message = web3_js_1.TransactionMessage.decompile(transaction.message, {
|
|
936
935
|
addressLookupTableAccounts: addressLookupTableAccounts,
|
|
937
936
|
});
|
|
938
|
-
const swapInstruction = message.instructions.find((ix) => ix.programId.equals((0, anchor_1.translateAddress)(
|
|
937
|
+
const swapInstruction = message.instructions.find((ix) => ix.programId.equals((0, anchor_1.translateAddress)(zebec_card_v2_sdk_1.JUPITER_AGGREGATOR_PROGRAM_ID)));
|
|
939
938
|
(0, assert_1.default)(swapInstruction, "Swap instruction not found in the transaction message");
|
|
940
|
-
const otherIxs = message.instructions.filter((ix) => !ix.programId.equals((0, anchor_1.translateAddress)(
|
|
939
|
+
const otherIxs = message.instructions.filter((ix) => !ix.programId.equals((0, anchor_1.translateAddress)(zebec_card_v2_sdk_1.JUPITER_AGGREGATOR_PROGRAM_ID)) &&
|
|
941
940
|
!ix.programId.equals(web3_js_1.ComputeBudgetProgram.programId));
|
|
942
941
|
const index = new anchor_1.BN(params.nextCardCounter.toString());
|
|
943
942
|
const swapAndLoadCarbonCardIx = await this.getSwapAndLoadCarbonCardInstruction(cardVault, cardVaultAta, inputMint, solana_common_1.TOKEN_PROGRAM_ID, usdc, revenueVault, revenueVaultAta, vaultOwner, {
|
|
@@ -1140,7 +1139,7 @@ class ZebecVaultService {
|
|
|
1140
1139
|
.getAccountInfo((0, anchor_1.translateAddress)(lookupTable))
|
|
1141
1140
|
.then((res) => {
|
|
1142
1141
|
if (!res) {
|
|
1143
|
-
throw new Error(`Lookup table account not found for key: ${(0, anchor_1.translateAddress)(
|
|
1142
|
+
throw new Error(`Lookup table account not found for key: ${(0, anchor_1.translateAddress)(zebec_card_v2_sdk_1.CARD_LOOKUP_TABLE_ADDRESS[this.network]).toString()}`);
|
|
1144
1143
|
}
|
|
1145
1144
|
return res.data;
|
|
1146
1145
|
});
|
|
@@ -1160,7 +1159,7 @@ class ZebecVaultService {
|
|
|
1160
1159
|
.getAccountInfo((0, anchor_1.translateAddress)(lookupTable))
|
|
1161
1160
|
.then((res) => {
|
|
1162
1161
|
if (!res) {
|
|
1163
|
-
throw new Error(`Lookup table account not found for key: ${(0, anchor_1.translateAddress)(
|
|
1162
|
+
throw new Error(`Lookup table account not found for key: ${(0, anchor_1.translateAddress)(zebec_card_v2_sdk_1.CARD_LOOKUP_TABLE_ADDRESS[this.network]).toString()}`);
|
|
1164
1163
|
}
|
|
1165
1164
|
return res.data;
|
|
1166
1165
|
});
|
|
@@ -1521,7 +1520,7 @@ class ZebecVaultService {
|
|
|
1521
1520
|
return acc;
|
|
1522
1521
|
}, []);
|
|
1523
1522
|
const ixFinal = await this.getExecuteProposalDirectInstruction(vaultOwner, actions, remainingAccounts);
|
|
1524
|
-
const lookupTables = await this.connection.getAddressLookupTable((0, anchor_1.translateAddress)(
|
|
1523
|
+
const lookupTables = await this.connection.getAddressLookupTable((0, anchor_1.translateAddress)(zebec_stake_sdk_1.STAKE_LOOKUP_TABLE_ADDRESS[this.network]));
|
|
1525
1524
|
const lookupTableAccount = lookupTables.value;
|
|
1526
1525
|
(0, assert_1.default)(lookupTableAccount, "Lookup table account not found");
|
|
1527
1526
|
return this._createTransactionPayload(vaultOwner, [ixFinal], [], [lookupTableAccount]);
|
|
@@ -1564,7 +1563,7 @@ class ZebecVaultService {
|
|
|
1564
1563
|
return acc;
|
|
1565
1564
|
}, []);
|
|
1566
1565
|
const ixFinal = await this.getExecuteProposalDirectInstruction(vaultOwner, actions, remainingAccounts);
|
|
1567
|
-
const lookupTables = await this.connection.getAddressLookupTable((0, anchor_1.translateAddress)(
|
|
1566
|
+
const lookupTables = await this.connection.getAddressLookupTable((0, anchor_1.translateAddress)(zebec_stake_sdk_1.STAKE_LOOKUP_TABLE_ADDRESS[this.network]));
|
|
1568
1567
|
const lookupTableAccount = lookupTables.value;
|
|
1569
1568
|
(0, assert_1.default)(lookupTableAccount, "Lookup table account not found");
|
|
1570
1569
|
return this._createTransactionPayload(vaultOwner, [ixFinal], [], [lookupTableAccount]);
|
package/package.json
CHANGED
|
@@ -1,51 +1,51 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
}
|
|
2
|
+
"author": "Zebec Network | Ashish Sapkota",
|
|
3
|
+
"dependencies": {
|
|
4
|
+
"@coral-xyz/anchor": "^0.31.1",
|
|
5
|
+
"@solana/spl-token": "^0.4.14",
|
|
6
|
+
"@solana/web3.js": "^1.98.2",
|
|
7
|
+
"@types/bn.js": "^5.2.0",
|
|
8
|
+
"@zebec-network/core-utils": "^1.1.1",
|
|
9
|
+
"@zebec-network/solana-common": "^2.3.1",
|
|
10
|
+
"@zebec-network/zebec-card-v2-sdk": "^2.6.0",
|
|
11
|
+
"@zebec-network/zebec-stake-sdk": "^1.3.1",
|
|
12
|
+
"@zebec-network/zebec-stream-sdk": "^3.1.1",
|
|
13
|
+
"bignumber.js": "^9.3.1",
|
|
14
|
+
"buffer": "^6.0.3"
|
|
15
|
+
},
|
|
16
|
+
"description": "An SDK for zebec vault solana program",
|
|
17
|
+
"devDependencies": {
|
|
18
|
+
"@types/mocha": "^10.0.10",
|
|
19
|
+
"@types/node": "^24.3.1",
|
|
20
|
+
"dotenv": "^17.2.2",
|
|
21
|
+
"mocha": "^11.7.2",
|
|
22
|
+
"prettier": "^3.6.2",
|
|
23
|
+
"rimraf": "^6.0.1",
|
|
24
|
+
"ts-mocha": "^11.1.0",
|
|
25
|
+
"ts-node": "^10.9.2",
|
|
26
|
+
"typescript": "^5.9.2"
|
|
27
|
+
},
|
|
28
|
+
"files": [
|
|
29
|
+
"dist",
|
|
30
|
+
"assets"
|
|
31
|
+
],
|
|
32
|
+
"keywords": [
|
|
33
|
+
"solana",
|
|
34
|
+
"zebec",
|
|
35
|
+
"zebec network",
|
|
36
|
+
"vualt",
|
|
37
|
+
"zebec vault"
|
|
38
|
+
],
|
|
39
|
+
"license": "MIT",
|
|
40
|
+
"main": "dist/index.js",
|
|
41
|
+
"name": "@zebec-network/zebec-vault-sdk",
|
|
42
|
+
"scripts": {
|
|
43
|
+
"build": "npm run clean && tsc",
|
|
44
|
+
"clean": "rimraf ./dist",
|
|
45
|
+
"format": "npx @biomejs/biome format --write ",
|
|
46
|
+
"test": "ts-mocha -p ./tsconfig.json -t 1000000000 test/**/*.test.ts",
|
|
47
|
+
"test:single": "ts-mocha -p ./tsconfig.json -t 1000000000"
|
|
48
|
+
},
|
|
49
|
+
"types": "dist/index.d.ts",
|
|
50
|
+
"version": "5.2.2"
|
|
51
|
+
}
|