@zebec-network/zebec-stream-sdk 3.0.0 → 3.1.0-dev.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/services/streamService.js +48 -25
- package/dist/types.d.ts +24 -3
- package/dist/utils.d.ts +4 -4
- package/dist/utils.js +15 -24
- package/package.json +1 -1
|
@@ -4,8 +4,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.ZebecStreamService = void 0;
|
|
7
|
-
const assert_1 = __importDefault(require("assert"));
|
|
8
|
-
const bignumber_js_1 = require("bignumber.js");
|
|
9
7
|
const anchor_1 = require("@coral-xyz/anchor");
|
|
10
8
|
const mpl_token_metadata_1 = require("@metaplex-foundation/mpl-token-metadata");
|
|
11
9
|
const umi_bundle_defaults_1 = require("@metaplex-foundation/umi-bundle-defaults");
|
|
@@ -14,6 +12,8 @@ const spl_token_1 = require("@solana/spl-token");
|
|
|
14
12
|
const web3_js_1 = require("@solana/web3.js");
|
|
15
13
|
const core_utils_1 = require("@zebec-network/core-utils");
|
|
16
14
|
const solana_common_1 = require("@zebec-network/solana-common");
|
|
15
|
+
const assert_1 = __importDefault(require("assert"));
|
|
16
|
+
const bignumber_js_1 = require("bignumber.js");
|
|
17
17
|
const artifacts_1 = require("../artifacts");
|
|
18
18
|
const constants_1 = require("../constants");
|
|
19
19
|
const pda_1 = require("../pda");
|
|
@@ -197,7 +197,9 @@ class ZebecStreamService {
|
|
|
197
197
|
.instruction();
|
|
198
198
|
}
|
|
199
199
|
async initializeStreamConfig(params) {
|
|
200
|
-
const admin = params.admin
|
|
200
|
+
const admin = params.admin
|
|
201
|
+
? (0, anchor_1.translateAddress)(params.admin)
|
|
202
|
+
: this.provider.publicKey;
|
|
201
203
|
if (!admin) {
|
|
202
204
|
throw new Error("Either provide admin or create provider with public key");
|
|
203
205
|
}
|
|
@@ -209,8 +211,12 @@ class ZebecStreamService {
|
|
|
209
211
|
const feeVault = (0, anchor_1.translateAddress)(params.config.feeVault);
|
|
210
212
|
const feeTiers = params.config.feeTiers.map((tier) => {
|
|
211
213
|
return {
|
|
212
|
-
minAmount: new anchor_1.BN((0, bignumber_js_1.BigNumber)(tier.minThreshold)
|
|
213
|
-
|
|
214
|
+
minAmount: new anchor_1.BN((0, bignumber_js_1.BigNumber)(tier.minThreshold)
|
|
215
|
+
.times(solana_common_1.TEN_BIGNUM.pow(solana_common_1.USDC_DECIMALS))
|
|
216
|
+
.toFixed(0)),
|
|
217
|
+
maxAmount: new anchor_1.BN((0, bignumber_js_1.BigNumber)(tier.maxThreshold)
|
|
218
|
+
.times(solana_common_1.TEN_BIGNUM.pow(solana_common_1.USDC_DECIMALS))
|
|
219
|
+
.toFixed(0)),
|
|
214
220
|
fee: new anchor_1.BN((0, core_utils_1.percentToBps)(tier.feeRateInPercent)),
|
|
215
221
|
};
|
|
216
222
|
});
|
|
@@ -226,7 +232,9 @@ class ZebecStreamService {
|
|
|
226
232
|
return this._createPayload(admin, [ix]);
|
|
227
233
|
}
|
|
228
234
|
async updateStreamConfig(params) {
|
|
229
|
-
const admin = params.admin
|
|
235
|
+
const admin = params.admin
|
|
236
|
+
? (0, anchor_1.translateAddress)(params.admin)
|
|
237
|
+
: this.provider.publicKey;
|
|
230
238
|
if (!admin) {
|
|
231
239
|
throw new Error("Either provide admin or create provider with public key");
|
|
232
240
|
}
|
|
@@ -238,8 +246,12 @@ class ZebecStreamService {
|
|
|
238
246
|
const feeVault = (0, anchor_1.translateAddress)(params.config.feeVault);
|
|
239
247
|
const feeTiers = params.config.feeTiers.map((tier) => {
|
|
240
248
|
return {
|
|
241
|
-
minAmount: new anchor_1.BN((0, bignumber_js_1.BigNumber)(tier.minThreshold)
|
|
242
|
-
|
|
249
|
+
minAmount: new anchor_1.BN((0, bignumber_js_1.BigNumber)(tier.minThreshold)
|
|
250
|
+
.times(solana_common_1.TEN_BIGNUM.pow(solana_common_1.USDC_DECIMALS))
|
|
251
|
+
.toFixed(0)),
|
|
252
|
+
maxAmount: new anchor_1.BN((0, bignumber_js_1.BigNumber)(tier.maxThreshold)
|
|
253
|
+
.times(solana_common_1.TEN_BIGNUM.pow(solana_common_1.USDC_DECIMALS))
|
|
254
|
+
.toFixed(0)),
|
|
243
255
|
fee: new anchor_1.BN((0, core_utils_1.percentToBps)(tier.feeRateInPercent)),
|
|
244
256
|
};
|
|
245
257
|
});
|
|
@@ -257,32 +269,31 @@ class ZebecStreamService {
|
|
|
257
269
|
async createStream(params) {
|
|
258
270
|
const receiver = (0, anchor_1.translateAddress)(params.receiver);
|
|
259
271
|
const sender = (0, anchor_1.translateAddress)(params.sender);
|
|
260
|
-
const feePayer = params.feePayer
|
|
272
|
+
const feePayer = params.feePayer
|
|
273
|
+
? (0, anchor_1.translateAddress)(params.feePayer)
|
|
274
|
+
: sender;
|
|
261
275
|
const streamToken = (0, anchor_1.translateAddress)(params.streamToken);
|
|
262
276
|
const [streamConfig] = (0, pda_1.deriveStreamConfigPda)(this.streamConfigName, this.programId);
|
|
263
277
|
const streamConfigAccount = await this.program.account.streamConfig.fetch(streamConfig);
|
|
264
278
|
const withdrawer = streamConfigAccount.withdrawAccount;
|
|
265
279
|
const autoWithdrawFrequencies = new Set(Array.from(streamConfigAccount.frequencies.map((f) => f.toNumber())));
|
|
266
|
-
if (params.automaticWithdrawal &&
|
|
280
|
+
if (params.automaticWithdrawal &&
|
|
281
|
+
!autoWithdrawFrequencies.has(params.autoWithdrawFrequency)) {
|
|
267
282
|
throw new Error("Invalid stream frequency");
|
|
268
283
|
}
|
|
269
284
|
const senderAta = (0, solana_common_1.getAssociatedTokenAddressSync)(streamToken, sender, true);
|
|
270
285
|
const streamMetadataKeypair = params.streamMetadataKeypair ?? web3_js_1.Keypair.generate();
|
|
271
286
|
const streamTokenDecimals = await (0, solana_common_1.getMintDecimals)(this.connection, streamToken);
|
|
272
|
-
const amount = (0, bignumber_js_1.BigNumber)(params.amount)
|
|
287
|
+
const amount = (0, bignumber_js_1.BigNumber)(params.amount)
|
|
288
|
+
.times(solana_common_1.TEN_BIGNUM.pow(streamTokenDecimals))
|
|
289
|
+
.toFixed(0);
|
|
273
290
|
const cliffPercentage = new anchor_1.BN((0, core_utils_1.percentToBps)(params.cliffPercentage));
|
|
274
291
|
const streamName = new Uint8Array(constants_1.STREAM_NAME_BUFFER_SIZE);
|
|
275
292
|
streamName.set(anchor_1.utils.bytes.utf8.encode(params.streamName));
|
|
276
293
|
const configAccount = await this.program.account.streamConfig.fetch(streamConfig);
|
|
277
|
-
const
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
maxThreshold: (0, bignumber_js_1.BigNumber)(tier.maxAmount.toString()).div(solana_common_1.UNITS_PER_USDC).toFixed(),
|
|
281
|
-
}));
|
|
282
|
-
const feeAmount = await (0, utils_1.calculateFeeTokenAmountForStream)(params.streamTokenSymbol, params.amount, params.feeTokenSymbol, feeTiers, this.network);
|
|
283
|
-
const feeToken = (0, anchor_1.translateAddress)(params.feeToken);
|
|
284
|
-
const feeTokenDecimals = await (0, solana_common_1.getMintDecimals)(this.connection, feeToken);
|
|
285
|
-
const parsedFeeAmount = (0, bignumber_js_1.BigNumber)(feeAmount).times(solana_common_1.TEN_BIGNUM.pow(feeTokenDecimals)).toFixed(0);
|
|
294
|
+
const feeInfo = await (0, utils_1.getFeeInfoForStream)(streamToken, amount, streamTokenDecimals, this.network);
|
|
295
|
+
const feeToken = (0, anchor_1.translateAddress)(feeInfo.feeToken.mintAddress);
|
|
296
|
+
const parsedFeeAmount = feeInfo.feeAmountRaw;
|
|
286
297
|
const feeVault = configAccount.feeVault;
|
|
287
298
|
const feeVaultAta = (0, solana_common_1.getAssociatedTokenAddressSync)(feeToken, feeVault, true);
|
|
288
299
|
const senderFeeTokenAta = (0, solana_common_1.getAssociatedTokenAddressSync)(feeToken, sender, true);
|
|
@@ -350,8 +361,14 @@ class ZebecStreamService {
|
|
|
350
361
|
}
|
|
351
362
|
async withdrawStream(params) {
|
|
352
363
|
const receiver = (0, anchor_1.translateAddress)(params.receiver);
|
|
353
|
-
const withdrawer = params.withdrawer
|
|
354
|
-
|
|
364
|
+
const withdrawer = params.withdrawer
|
|
365
|
+
? (0, anchor_1.translateAddress)(params.withdrawer)
|
|
366
|
+
: receiver;
|
|
367
|
+
const feePayer = params.feePayer
|
|
368
|
+
? (0, anchor_1.translateAddress)(params.feePayer)
|
|
369
|
+
: params.withdrawer
|
|
370
|
+
? withdrawer
|
|
371
|
+
: receiver;
|
|
355
372
|
const streamMetadata = (0, anchor_1.translateAddress)(params.streamMetadata);
|
|
356
373
|
const streamMetadataAccount = await this.program.account.paymentStream.fetch(streamMetadata);
|
|
357
374
|
const streamToken = streamMetadataAccount.financials.streamToken;
|
|
@@ -388,8 +405,12 @@ class ZebecStreamService {
|
|
|
388
405
|
frequencies: configInfo.frequencies.map((frequency) => frequency.toNumber()),
|
|
389
406
|
feeTiers: configInfo.feeTiers.tiers.map((tier) => ({
|
|
390
407
|
feeRateInPercent: (0, core_utils_1.bpsToPercent)(tier.fee.toNumber()),
|
|
391
|
-
minThreshold: (0, bignumber_js_1.BigNumber)(tier.minAmount.toString())
|
|
392
|
-
|
|
408
|
+
minThreshold: (0, bignumber_js_1.BigNumber)(tier.minAmount.toString())
|
|
409
|
+
.div(solana_common_1.UNITS_PER_USDC)
|
|
410
|
+
.toFixed(),
|
|
411
|
+
maxThreshold: (0, bignumber_js_1.BigNumber)(tier.maxAmount.toString())
|
|
412
|
+
.div(solana_common_1.UNITS_PER_USDC)
|
|
413
|
+
.toFixed(),
|
|
393
414
|
})),
|
|
394
415
|
feeVault: configInfo.feeVault,
|
|
395
416
|
};
|
|
@@ -419,7 +440,9 @@ class ZebecStreamService {
|
|
|
419
440
|
freezeAuthority: mintData.parsed.info.freezeAuthority
|
|
420
441
|
? new web3_js_1.PublicKey(mintData.parsed.info.freezeAuthority)
|
|
421
442
|
: null,
|
|
422
|
-
supply: (0, bignumber_js_1.BigNumber)(mintData.parsed.info.supply)
|
|
443
|
+
supply: (0, bignumber_js_1.BigNumber)(mintData.parsed.info.supply)
|
|
444
|
+
.div(solana_common_1.TEN_BIGNUM.pow(mintData.parsed.info.decimals))
|
|
445
|
+
.toFixed(),
|
|
423
446
|
isInitialized: Boolean(mintData.parsed.info.isInitialized),
|
|
424
447
|
mintAuthority: mintData.parsed.info.mintAuthority
|
|
425
448
|
? new web3_js_1.PublicKey(mintData.parsed.info.mintAuthority)
|
package/dist/types.d.ts
CHANGED
|
@@ -67,9 +67,6 @@ export type CreateStreamParams = {
|
|
|
67
67
|
receiver: Address;
|
|
68
68
|
sender: Address;
|
|
69
69
|
streamToken: Address;
|
|
70
|
-
streamTokenSymbol: string;
|
|
71
|
-
feeToken: Address;
|
|
72
|
-
feeTokenSymbol: string;
|
|
73
70
|
amount: Numeric;
|
|
74
71
|
automaticWithdrawal: boolean;
|
|
75
72
|
cancelableByRecipient: boolean;
|
|
@@ -137,3 +134,27 @@ export type ChangeStreamReceiverParams = {
|
|
|
137
134
|
newRecipient: Address;
|
|
138
135
|
signer: Address;
|
|
139
136
|
};
|
|
137
|
+
export type StreamFeeInfo = {
|
|
138
|
+
tokenSymbol: string;
|
|
139
|
+
mintAddress: string;
|
|
140
|
+
chain: string;
|
|
141
|
+
streamAmount: string;
|
|
142
|
+
streamAmountUi: string;
|
|
143
|
+
tokenPriceUsd: number;
|
|
144
|
+
streamAmountUsd: number;
|
|
145
|
+
feeTier: {
|
|
146
|
+
tier: number;
|
|
147
|
+
range: string;
|
|
148
|
+
feeRatePercent: number;
|
|
149
|
+
};
|
|
150
|
+
feeRatePercent: number;
|
|
151
|
+
feeAmountUsd: number;
|
|
152
|
+
feeToken: {
|
|
153
|
+
symbol: string;
|
|
154
|
+
decimals: number;
|
|
155
|
+
priceUsd: number;
|
|
156
|
+
mintAddress: string;
|
|
157
|
+
};
|
|
158
|
+
feeAmount: number;
|
|
159
|
+
feeAmountRaw: string;
|
|
160
|
+
};
|
package/dist/utils.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
|
|
3
|
-
export declare function
|
|
4
|
-
export declare function getFeeRateForUsdAmount(amount: BigNumber, feeTiers: FeeTier[]): string;
|
|
1
|
+
import type { PublicKey } from "@solana/web3.js";
|
|
2
|
+
import type { FeeTier, RpcNetwork, StreamFeeInfo } from "./types";
|
|
3
|
+
export declare function getFeeInfoForStream(streamToken: PublicKey, parsedStreamTokenAmount: BigNumber.Value, streamTokenDecimals: number, network: RpcNetwork): Promise<StreamFeeInfo>;
|
|
4
|
+
export declare function getFeeRateForUsdAmount(amount: BigNumber.Value, feeTiers: FeeTier[]): string;
|
package/dist/utils.js
CHANGED
|
@@ -1,40 +1,31 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
4
|
-
exports.calculateFeeTokenAmountForStream = calculateFeeTokenAmountForStream;
|
|
3
|
+
exports.getFeeInfoForStream = getFeeInfoForStream;
|
|
5
4
|
exports.getFeeRateForUsdAmount = getFeeRateForUsdAmount;
|
|
6
|
-
const bignumber_js_1 = require("bignumber.js");
|
|
7
5
|
const core_utils_1 = require("@zebec-network/core-utils");
|
|
6
|
+
const bignumber_js_1 = require("bignumber.js");
|
|
8
7
|
const constants_1 = require("./constants");
|
|
9
|
-
async function
|
|
10
|
-
const
|
|
8
|
+
async function getFeeInfoForStream(streamToken, parsedStreamTokenAmount, streamTokenDecimals, network) {
|
|
9
|
+
const urlsParams = new URLSearchParams({
|
|
10
|
+
streamToken: streamToken.toBase58(),
|
|
11
|
+
chain: "SOLANA",
|
|
12
|
+
amount: (0, bignumber_js_1.BigNumber)(parsedStreamTokenAmount).toFixed(0),
|
|
13
|
+
decimals: streamTokenDecimals.toString(),
|
|
14
|
+
});
|
|
15
|
+
const url = `${constants_1.SUPERAPP_BACKEND_URL[network]}/l1-stream/fees/stream-quote?${urlsParams}`;
|
|
16
|
+
console.debug("fetching fee token amount from url:", url);
|
|
11
17
|
const response = await fetch(url);
|
|
12
18
|
if (!response.ok) {
|
|
13
19
|
const body = await response.text().catch(() => "");
|
|
14
|
-
throw new Error(`Failed to fetch token
|
|
20
|
+
throw new Error(`Failed to fetch fee token amount: ${response.status} ${response.statusText} ${body}`.trim());
|
|
15
21
|
}
|
|
16
22
|
const data = await response.json();
|
|
17
|
-
|
|
18
|
-
console.debug("Unexpected response format when fetching token price:", data);
|
|
19
|
-
throw new Error(`Invalid response format when fetching token price for symbol: ${tokenSymbol}, network: ${network}`);
|
|
20
|
-
}
|
|
21
|
-
return Number(data.exchangeRate);
|
|
22
|
-
}
|
|
23
|
-
async function calculateFeeTokenAmountForStream(streamTokenSymbol, streamTokenAmount, feeTokenSymbol, feeTiers, network) {
|
|
24
|
-
const oneStreamTokenPriceInUsd = await getTokenUsdPrice(streamTokenSymbol, network);
|
|
25
|
-
const oneFeeTokenPriceInUsd = await getTokenUsdPrice(feeTokenSymbol, network);
|
|
26
|
-
if (oneFeeTokenPriceInUsd === 0) {
|
|
27
|
-
throw new Error(`Fee token price is zero for symbol: ${feeTokenSymbol}, network: ${network}`);
|
|
28
|
-
}
|
|
29
|
-
const streamTokenAmountUsdPrice = new bignumber_js_1.BigNumber(streamTokenAmount).times(oneStreamTokenPriceInUsd);
|
|
30
|
-
const feeRateInBps = getFeeRateForUsdAmount(streamTokenAmountUsdPrice, feeTiers);
|
|
31
|
-
const feeAmountUsdPrice = streamTokenAmountUsdPrice.times(feeRateInBps).div(10000);
|
|
32
|
-
const feeTokenAmount = feeAmountUsdPrice.div(oneFeeTokenPriceInUsd);
|
|
33
|
-
return feeTokenAmount;
|
|
23
|
+
return data;
|
|
34
24
|
}
|
|
35
25
|
function getFeeRateForUsdAmount(amount, feeTiers) {
|
|
36
26
|
feeTiers.sort((a, b) => (0, bignumber_js_1.BigNumber)(a.minThreshold).comparedTo((0, bignumber_js_1.BigNumber)(b.minThreshold)) ?? 0);
|
|
37
|
-
const tier = feeTiers.find((tier) => amount.gte(tier.minThreshold) &&
|
|
27
|
+
const tier = feeTiers.find((tier) => (0, bignumber_js_1.BigNumber)(amount).gte(tier.minThreshold) &&
|
|
28
|
+
(0, bignumber_js_1.BigNumber)(amount).lt(tier.maxThreshold));
|
|
38
29
|
if (!tier) {
|
|
39
30
|
throw new Error(`No fee tier found for amount: ${amount}`);
|
|
40
31
|
}
|
package/package.json
CHANGED