@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.
@@ -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 ? (0, anchor_1.translateAddress)(params.admin) : this.provider.publicKey;
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).times(solana_common_1.TEN_BIGNUM.pow(solana_common_1.USDC_DECIMALS)).toFixed(0)),
213
- maxAmount: new anchor_1.BN((0, bignumber_js_1.BigNumber)(tier.maxThreshold).times(solana_common_1.TEN_BIGNUM.pow(solana_common_1.USDC_DECIMALS)).toFixed(0)),
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 ? (0, anchor_1.translateAddress)(params.admin) : this.provider.publicKey;
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).times(solana_common_1.TEN_BIGNUM.pow(solana_common_1.USDC_DECIMALS)).toFixed(0)),
242
- maxAmount: new anchor_1.BN((0, bignumber_js_1.BigNumber)(tier.maxThreshold).times(solana_common_1.TEN_BIGNUM.pow(solana_common_1.USDC_DECIMALS)).toFixed(0)),
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 ? (0, anchor_1.translateAddress)(params.feePayer) : sender;
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 && !autoWithdrawFrequencies.has(params.autoWithdrawFrequency)) {
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).times(solana_common_1.TEN_BIGNUM.pow(streamTokenDecimals)).toFixed(0);
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 feeTiers = configAccount.feeTiers.tiers.map((tier) => ({
278
- feeRateInPercent: (0, core_utils_1.bpsToPercent)(tier.fee.toNumber()),
279
- minThreshold: (0, bignumber_js_1.BigNumber)(tier.minAmount.toString()).div(solana_common_1.UNITS_PER_USDC).toFixed(),
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 ? (0, anchor_1.translateAddress)(params.withdrawer) : receiver;
354
- const feePayer = params.feePayer ? (0, anchor_1.translateAddress)(params.feePayer) : params.withdrawer ? withdrawer : receiver;
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()).div(solana_common_1.UNITS_PER_USDC).toFixed(),
392
- maxThreshold: (0, bignumber_js_1.BigNumber)(tier.maxAmount.toString()).div(solana_common_1.UNITS_PER_USDC).toFixed(),
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).div(solana_common_1.TEN_BIGNUM.pow(mintData.parsed.info.decimals)).toFixed(),
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 { FeeTier, Numeric, RpcNetwork } from "./types";
2
- export declare function getTokenUsdPrice(tokenSymbol: string, network: RpcNetwork): Promise<number>;
3
- export declare function calculateFeeTokenAmountForStream(streamTokenSymbol: string, streamTokenAmount: Numeric, feeTokenSymbol: string, feeTiers: FeeTier[], network: RpcNetwork): Promise<BigNumber>;
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.getTokenUsdPrice = getTokenUsdPrice;
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 getTokenUsdPrice(tokenSymbol, network) {
10
- const url = `${constants_1.SUPERAPP_BACKEND_URL[network]}/tokens/quotes/${encodeURIComponent(`${tokenSymbol}_USD`)}/1?type=EXACT_IN&chainName=SOLANA`;
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 price for symbol: ${tokenSymbol}, network: ${network}, status: ${response.status} ${body}`);
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
- if (!data || !("exchangeRate" in data)) {
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) && amount.lt(tier.maxThreshold));
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
@@ -40,5 +40,5 @@
40
40
  "test:single": "ts-mocha -p ./tsconfig.json -t 1000000000"
41
41
  },
42
42
  "types": "dist/index.d.ts",
43
- "version": "3.0.0"
43
+ "version": "3.1.0-dev.1"
44
44
  }