@zebec-network/zebec-stream-sdk 2.0.0 → 3.0.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.
@@ -407,6 +407,11 @@ export type ZebecStream = {
407
407
  {
408
408
  kind: "const";
409
409
  value: [99, 111, 110, 102, 105, 103];
410
+ },
411
+ {
412
+ kind: "account";
413
+ path: "stream_config.config_name";
414
+ account: "streamConfig";
410
415
  }
411
416
  ];
412
417
  };
@@ -459,6 +464,10 @@ export type ZebecStream = {
459
464
  {
460
465
  kind: "const";
461
466
  value: [99, 111, 110, 102, 105, 103];
467
+ },
468
+ {
469
+ kind: "arg";
470
+ path: "params.config_name";
462
471
  }
463
472
  ];
464
473
  };
@@ -512,6 +521,11 @@ export type ZebecStream = {
512
521
  {
513
522
  kind: "const";
514
523
  value: [99, 111, 110, 102, 105, 103];
524
+ },
525
+ {
526
+ kind: "account";
527
+ path: "stream_config.config_name";
528
+ account: "streamConfig";
515
529
  }
516
530
  ];
517
531
  };
@@ -549,6 +563,11 @@ export type ZebecStream = {
549
563
  {
550
564
  kind: "const";
551
565
  value: [99, 111, 110, 102, 105, 103];
566
+ },
567
+ {
568
+ kind: "account";
569
+ path: "stream_config.config_name";
570
+ account: "streamConfig";
552
571
  }
553
572
  ];
554
573
  };
@@ -703,6 +722,11 @@ export type ZebecStream = {
703
722
  {
704
723
  kind: "const";
705
724
  value: [99, 111, 110, 102, 105, 103];
725
+ },
726
+ {
727
+ kind: "account";
728
+ path: "stream_config.config_name";
729
+ account: "streamConfig";
706
730
  }
707
731
  ];
708
732
  };
@@ -964,11 +988,53 @@ export type ZebecStream = {
964
988
  ];
965
989
  };
966
990
  },
991
+ {
992
+ name: "feeMap";
993
+ type: {
994
+ kind: "struct";
995
+ fields: [
996
+ {
997
+ name: "tiers";
998
+ type: {
999
+ vec: {
1000
+ defined: {
1001
+ name: "feeTier";
1002
+ };
1003
+ };
1004
+ };
1005
+ }
1006
+ ];
1007
+ };
1008
+ },
1009
+ {
1010
+ name: "feeTier";
1011
+ type: {
1012
+ kind: "struct";
1013
+ fields: [
1014
+ {
1015
+ name: "minAmount";
1016
+ type: "u64";
1017
+ },
1018
+ {
1019
+ name: "maxAmount";
1020
+ type: "u64";
1021
+ },
1022
+ {
1023
+ name: "fee";
1024
+ type: "u64";
1025
+ }
1026
+ ];
1027
+ };
1028
+ },
967
1029
  {
968
1030
  name: "initializeConfigParams";
969
1031
  type: {
970
1032
  kind: "struct";
971
1033
  fields: [
1034
+ {
1035
+ name: "configName";
1036
+ type: "string";
1037
+ },
972
1038
  {
973
1039
  name: "withdrawAccount";
974
1040
  type: "pubkey";
@@ -986,6 +1052,20 @@ export type ZebecStream = {
986
1052
  type: {
987
1053
  vec: "u64";
988
1054
  };
1055
+ },
1056
+ {
1057
+ name: "feeTier";
1058
+ type: {
1059
+ vec: {
1060
+ defined: {
1061
+ name: "feeTier";
1062
+ };
1063
+ };
1064
+ };
1065
+ },
1066
+ {
1067
+ name: "feeVault";
1068
+ type: "pubkey";
989
1069
  }
990
1070
  ];
991
1071
  };
@@ -1117,6 +1197,10 @@ export type ZebecStream = {
1117
1197
  type: {
1118
1198
  kind: "struct";
1119
1199
  fields: [
1200
+ {
1201
+ name: "configName";
1202
+ type: "string";
1203
+ },
1120
1204
  {
1121
1205
  name: "admin";
1122
1206
  type: "pubkey";
@@ -1144,6 +1228,18 @@ export type ZebecStream = {
1144
1228
  type: {
1145
1229
  vec: "u64";
1146
1230
  };
1231
+ },
1232
+ {
1233
+ name: "feeTiers";
1234
+ type: {
1235
+ defined: {
1236
+ name: "feeMap";
1237
+ };
1238
+ };
1239
+ },
1240
+ {
1241
+ name: "feeVault";
1242
+ type: "pubkey";
1147
1243
  }
1148
1244
  ];
1149
1245
  };
@@ -367,6 +367,11 @@
367
367
  {
368
368
  "kind": "const",
369
369
  "value": [99, 111, 110, 102, 105, 103]
370
+ },
371
+ {
372
+ "account": "StreamConfig",
373
+ "kind": "account",
374
+ "path": "stream_config.config_name"
370
375
  }
371
376
  ]
372
377
  }
@@ -418,6 +423,10 @@
418
423
  {
419
424
  "kind": "const",
420
425
  "value": [99, 111, 110, 102, 105, 103]
426
+ },
427
+ {
428
+ "kind": "arg",
429
+ "path": "params.config_name"
421
430
  }
422
431
  ]
423
432
  },
@@ -471,6 +480,11 @@
471
480
  {
472
481
  "kind": "const",
473
482
  "value": [99, 111, 110, 102, 105, 103]
483
+ },
484
+ {
485
+ "account": "StreamConfig",
486
+ "kind": "account",
487
+ "path": "stream_config.config_name"
474
488
  }
475
489
  ]
476
490
  },
@@ -508,6 +522,11 @@
508
522
  {
509
523
  "kind": "const",
510
524
  "value": [99, 111, 110, 102, 105, 103]
525
+ },
526
+ {
527
+ "account": "StreamConfig",
528
+ "kind": "account",
529
+ "path": "stream_config.config_name"
511
530
  }
512
531
  ]
513
532
  },
@@ -603,6 +622,11 @@
603
622
  {
604
623
  "kind": "const",
605
624
  "value": [99, 111, 110, 102, 105, 103]
625
+ },
626
+ {
627
+ "account": "StreamConfig",
628
+ "kind": "account",
629
+ "path": "stream_config.config_name"
606
630
  }
607
631
  ]
608
632
  }
@@ -725,10 +749,52 @@
725
749
  "kind": "struct"
726
750
  }
727
751
  },
752
+ {
753
+ "name": "FeeMap",
754
+ "type": {
755
+ "fields": [
756
+ {
757
+ "name": "tiers",
758
+ "type": {
759
+ "vec": {
760
+ "defined": {
761
+ "name": "FeeTier"
762
+ }
763
+ }
764
+ }
765
+ }
766
+ ],
767
+ "kind": "struct"
768
+ }
769
+ },
770
+ {
771
+ "name": "FeeTier",
772
+ "type": {
773
+ "fields": [
774
+ {
775
+ "name": "min_amount",
776
+ "type": "u64"
777
+ },
778
+ {
779
+ "name": "max_amount",
780
+ "type": "u64"
781
+ },
782
+ {
783
+ "name": "fee",
784
+ "type": "u64"
785
+ }
786
+ ],
787
+ "kind": "struct"
788
+ }
789
+ },
728
790
  {
729
791
  "name": "InitializeConfigParams",
730
792
  "type": {
731
793
  "fields": [
794
+ {
795
+ "name": "config_name",
796
+ "type": "string"
797
+ },
732
798
  {
733
799
  "name": "withdraw_account",
734
800
  "type": "pubkey"
@@ -746,6 +812,20 @@
746
812
  "type": {
747
813
  "vec": "u64"
748
814
  }
815
+ },
816
+ {
817
+ "name": "fee_tier",
818
+ "type": {
819
+ "vec": {
820
+ "defined": {
821
+ "name": "FeeTier"
822
+ }
823
+ }
824
+ }
825
+ },
826
+ {
827
+ "name": "fee_vault",
828
+ "type": "pubkey"
749
829
  }
750
830
  ],
751
831
  "kind": "struct"
@@ -877,6 +957,10 @@
877
957
  "name": "StreamConfig",
878
958
  "type": {
879
959
  "fields": [
960
+ {
961
+ "name": "config_name",
962
+ "type": "string"
963
+ },
880
964
  {
881
965
  "name": "admin",
882
966
  "type": "pubkey"
@@ -904,6 +988,18 @@
904
988
  "type": {
905
989
  "vec": "u64"
906
990
  }
991
+ },
992
+ {
993
+ "name": "fee_tiers",
994
+ "type": {
995
+ "defined": {
996
+ "name": "FeeMap"
997
+ }
998
+ }
999
+ },
1000
+ {
1001
+ "name": "fee_vault",
1002
+ "type": "pubkey"
907
1003
  }
908
1004
  ],
909
1005
  "kind": "struct"
@@ -1,4 +1,5 @@
1
+ import type { RpcNetwork } from "./types";
1
2
  export declare const STREAM_NAME_BUFFER_SIZE = 128;
2
- export type Network = "mainnet-beta" | "devnet";
3
- export declare const STREAM_PROGRAM_ID: Record<Network, string>;
4
- export declare const STREAM_PROGRAM_LOOKUP_TABLE_ADDRESS: Record<Network, string>;
3
+ export declare const STREAM_PROGRAM_ID: Record<RpcNetwork, string>;
4
+ export declare const STREAM_PROGRAM_LOOKUP_TABLE_ADDRESS: Record<RpcNetwork, string>;
5
+ export declare const SUPERAPP_BACKEND_URL: Record<RpcNetwork, string>;
package/dist/constants.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.STREAM_PROGRAM_LOOKUP_TABLE_ADDRESS = exports.STREAM_PROGRAM_ID = exports.STREAM_NAME_BUFFER_SIZE = void 0;
3
+ exports.SUPERAPP_BACKEND_URL = exports.STREAM_PROGRAM_LOOKUP_TABLE_ADDRESS = exports.STREAM_PROGRAM_ID = exports.STREAM_NAME_BUFFER_SIZE = void 0;
4
4
  exports.STREAM_NAME_BUFFER_SIZE = 128;
5
5
  exports.STREAM_PROGRAM_ID = {
6
6
  "mainnet-beta": "zSTRMmYcFF8SPdHmsAmAUjBnx4zDHvnqqGz2mPcc5QC",
@@ -8,5 +8,9 @@ exports.STREAM_PROGRAM_ID = {
8
8
  };
9
9
  exports.STREAM_PROGRAM_LOOKUP_TABLE_ADDRESS = {
10
10
  devnet: "HJmEzSXzJrtSdgBZSaedQ51WaD4LkT1r5zR2yT1QERqv",
11
- "mainnet-beta": "",
11
+ "mainnet-beta": "43N5otEu7k7TzkKsdhkwiYGrdKjBejetWQbF9cJPtY6i",
12
+ };
13
+ exports.SUPERAPP_BACKEND_URL = {
14
+ "mainnet-beta": "https://superapp-backend.zebec.io",
15
+ devnet: "https://dev-super.api.zebec.io",
12
16
  };
package/dist/pda.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Address } from "@coral-xyz/anchor";
1
+ import { type Address } from "@coral-xyz/anchor";
2
2
  import { PublicKey } from "@solana/web3.js";
3
- export declare function deriveStreamConfigPda(programId: Address): [PublicKey, number];
3
+ export declare function deriveStreamConfigPda(configName: string, programId: Address): [PublicKey, number];
4
4
  export declare function deriveStreamVaultPda(metatadata: Address, programId: Address): [PublicKey, number];
package/dist/pda.js CHANGED
@@ -7,8 +7,8 @@ const web3_js_1 = require("@solana/web3.js");
7
7
  const SEEDS = {
8
8
  STREAM_CONFIG: anchor_1.utils.bytes.utf8.encode("config"),
9
9
  };
10
- function deriveStreamConfigPda(programId) {
11
- return web3_js_1.PublicKey.findProgramAddressSync([Buffer.from(SEEDS.STREAM_CONFIG)], (0, anchor_1.translateAddress)(programId));
10
+ function deriveStreamConfigPda(configName, programId) {
11
+ return web3_js_1.PublicKey.findProgramAddressSync([Buffer.from(SEEDS.STREAM_CONFIG), anchor_1.utils.bytes.utf8.encode(configName)], (0, anchor_1.translateAddress)(programId));
12
12
  }
13
13
  function deriveStreamVaultPda(metatadata, programId) {
14
14
  return web3_js_1.PublicKey.findProgramAddressSync([(0, anchor_1.translateAddress)(metatadata).toBuffer()], (0, anchor_1.translateAddress)(programId));
@@ -1,28 +1,42 @@
1
- import { Address, BN, Program, Provider } from "@coral-xyz/anchor";
2
- import { Commitment, Connection, Keypair, PublicKey, TransactionInstruction } from "@solana/web3.js";
1
+ import { type Address, BN, Program, type Provider } from "@coral-xyz/anchor";
2
+ import { type Commitment, type Connection, PublicKey, type TransactionInstruction } from "@solana/web3.js";
3
3
  import { TransactionPayload } from "@zebec-network/solana-common";
4
- import { ZebecStreamIdl } from "../artifacts";
5
- import { Numeric, StreamConfigInfo, StreamMetadataInfo, TokenMetadata } from "../types";
4
+ import { type ZebecStreamIdl } from "../artifacts";
5
+ import type { CancelStreamParams, ChangeStreamReceiverParams, CreateStreamParams, InitializeStreamConfigParams, RpcNetwork, StreamConfigInfo, StreamMetadataInfo, TokenMetadata, UpdateStreamConfigParams, WhiteListTokensParams, WithdrawStreamParams } from "../types";
6
6
  export declare class ZebecStreamService {
7
7
  readonly provider: Provider;
8
- readonly network: "mainnet-beta" | "devnet";
8
+ readonly network: RpcNetwork;
9
9
  readonly program: Program<ZebecStreamIdl>;
10
- constructor(provider: Provider, network: "mainnet-beta" | "devnet", program: Program<ZebecStreamIdl>);
11
- static create(provider: Provider, network: "mainnet-beta" | "devnet"): ZebecStreamService;
10
+ constructor(provider: Provider, network: RpcNetwork, program: Program<ZebecStreamIdl>);
11
+ static create(provider: Provider, network: RpcNetwork): ZebecStreamService;
12
12
  private _createPayload;
13
13
  get connection(): Connection;
14
14
  get programId(): PublicKey;
15
- getInitializeStreamConfigInstruction(admin: PublicKey, config: {
15
+ getInitializeStreamConfigInstruction(admin: PublicKey, streamConfig: PublicKey, config: {
16
16
  baseFee: BN;
17
17
  frequencies: BN[];
18
18
  platformFee: BN;
19
19
  withdrawAccount: PublicKey;
20
+ configName: string;
21
+ feeTiers: {
22
+ minAmount: BN;
23
+ maxAmount: BN;
24
+ fee: BN;
25
+ }[];
26
+ feeVault: PublicKey;
20
27
  }): Promise<TransactionInstruction>;
21
- getUpdateStreamConfigInstruction(admin: PublicKey, config: {
28
+ getUpdateStreamConfigInstruction(admin: PublicKey, streamConfig: PublicKey, config: {
22
29
  baseFee: BN;
23
30
  frequencies: BN[];
24
31
  platformFee: BN;
25
32
  withdrawAccount: PublicKey;
33
+ configName: string;
34
+ feeTiers: {
35
+ minAmount: BN;
36
+ maxAmount: BN;
37
+ fee: BN;
38
+ }[];
39
+ feeVault: PublicKey;
26
40
  }): Promise<TransactionInstruction>;
27
41
  getCreateStreamInstruction(feePayer: PublicKey, receiver: PublicKey, senderAta: PublicKey, streamToken: PublicKey, withdrawAccount: PublicKey, sender: PublicKey, streamMetadata: PublicKey, streamData: {
28
42
  amount: BN;
@@ -56,70 +70,7 @@ export declare class ZebecStreamService {
56
70
  withdrawStream(params: WithdrawStreamParams): Promise<TransactionPayload>;
57
71
  whiteListTokens(params: WhiteListTokensParams): Promise<TransactionPayload>;
58
72
  changeStreamReceiver(params: ChangeStreamReceiverParams): Promise<TransactionPayload>;
59
- getStreamConfigInfo(commitment?: Commitment): Promise<StreamConfigInfo>;
60
- getWhitelistedTokens(commitment?: "processed" | "confirmed" | "finalized"): Promise<TokenMetadata[]>;
73
+ getStreamConfigInfo(configName: string, commitment?: Commitment): Promise<StreamConfigInfo>;
74
+ getWhitelistedTokens(configName: string, commitment?: "processed" | "confirmed" | "finalized"): Promise<TokenMetadata[]>;
61
75
  getStreamMetadataInfo(streamMetadata: Address, commitment?: Commitment): Promise<StreamMetadataInfo>;
62
76
  }
63
- export type CreateStreamParams = {
64
- feePayer?: Address;
65
- receiver: Address;
66
- sender: Address;
67
- streamToken: Address;
68
- amount: Numeric;
69
- automaticWithdrawal: boolean;
70
- cancelableByRecipient: boolean;
71
- cancelableBySender: boolean;
72
- cliffPercentage: Numeric;
73
- duration: number;
74
- isPausable: boolean;
75
- startNow: boolean;
76
- startTime: number;
77
- autoWithdrawFrequency: number;
78
- streamName: string;
79
- transferableByRecipient: boolean;
80
- transferableBySender: boolean;
81
- canTopup: boolean;
82
- rateUpdatable: boolean;
83
- streamMetadataKeypair?: Keypair;
84
- };
85
- export type InitializeStreamConfigParams = {
86
- admin?: Address;
87
- config: {
88
- baseFeePercent: Numeric;
89
- frequencies: number[];
90
- platformFeePercent: Numeric;
91
- withdrawAccount: Address;
92
- };
93
- };
94
- export type UpdateStreamConfigParams = {
95
- admin?: Address;
96
- config: {
97
- baseFeePercent: Numeric;
98
- frequencies: number[];
99
- platformFeePercent: Numeric;
100
- withdrawAccount: Address;
101
- };
102
- };
103
- export type CancelStreamParams = {
104
- feePayer?: Address;
105
- streamMetadata: Address;
106
- user: Address;
107
- };
108
- export type PauseResumeStreamParams = {
109
- streamMetadata: Address;
110
- };
111
- export type WithdrawStreamParams = {
112
- streamMetadata: Address;
113
- withdrawer?: Address;
114
- feePayer?: Address;
115
- receiver: Address;
116
- };
117
- export type WhiteListTokensParams = {
118
- admin: Address;
119
- tokens: Address[];
120
- };
121
- export type ChangeStreamReceiverParams = {
122
- streamMetadata: Address;
123
- newRecipient: Address;
124
- signer: Address;
125
- };
@@ -4,18 +4,20 @@ 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");
12
10
  const umi_web3js_adapters_1 = require("@metaplex-foundation/umi-web3js-adapters");
11
+ const spl_token_1 = require("@solana/spl-token");
13
12
  const web3_js_1 = require("@solana/web3.js");
14
13
  const core_utils_1 = require("@zebec-network/core-utils");
15
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");
16
17
  const artifacts_1 = require("../artifacts");
17
18
  const constants_1 = require("../constants");
18
19
  const pda_1 = require("../pda");
20
+ const utils_1 = require("../utils");
19
21
  class ZebecStreamService {
20
22
  provider;
21
23
  network;
@@ -44,7 +46,7 @@ class ZebecStreamService {
44
46
  }
45
47
  async _createPayload(payerKey, instructions, signers, addressLookupTableAccounts) {
46
48
  const errorMap = new Map();
47
- this.program.idl.errors.forEach((error) => errorMap.set(error.code, error.msg));
49
+ this.program.idl.errors.map((error) => errorMap.set(error.code, error.msg));
48
50
  const provider = this.provider;
49
51
  let signTransaction;
50
52
  if (provider instanceof anchor_1.AnchorProvider) {
@@ -65,29 +67,37 @@ class ZebecStreamService {
65
67
  get programId() {
66
68
  return this.program.programId;
67
69
  }
68
- async getInitializeStreamConfigInstruction(admin, config) {
70
+ async getInitializeStreamConfigInstruction(admin, streamConfig, config) {
69
71
  return this.program.methods
70
72
  .initializeConfig({
71
73
  baseFee: config.baseFee,
72
74
  frequencies: config.frequencies,
73
75
  platformFee: config.platformFee,
74
76
  withdrawAccount: config.withdrawAccount,
77
+ configName: config.configName,
78
+ feeTier: config.feeTiers,
79
+ feeVault: config.feeVault,
75
80
  })
76
- .accounts({
81
+ .accountsPartial({
77
82
  admin,
83
+ streamConfig,
78
84
  })
79
85
  .instruction();
80
86
  }
81
- async getUpdateStreamConfigInstruction(admin, config) {
87
+ async getUpdateStreamConfigInstruction(admin, streamConfig, config) {
82
88
  return this.program.methods
83
89
  .updateConfig({
84
90
  baseFee: config.baseFee,
85
91
  frequencies: config.frequencies,
86
92
  platformFee: config.platformFee,
87
93
  withdrawAccount: config.withdrawAccount,
94
+ configName: config.configName,
95
+ feeTier: config.feeTiers,
96
+ feeVault: config.feeVault,
88
97
  })
89
- .accounts({
98
+ .accountsPartial({
90
99
  admin,
100
+ streamConfig,
91
101
  })
92
102
  .instruction();
93
103
  }
@@ -187,15 +197,27 @@ class ZebecStreamService {
187
197
  if (!admin) {
188
198
  throw new Error("Either provide admin or create provider with public key");
189
199
  }
200
+ const [streamConfig] = (0, pda_1.deriveStreamConfigPda)(params.config.configName, this.programId);
190
201
  const baseFee = new anchor_1.BN((0, core_utils_1.percentToBps)(params.config.baseFeePercent));
191
202
  const frequencies = params.config.frequencies.map((frequency) => new anchor_1.BN(frequency));
192
203
  const platformFee = new anchor_1.BN((0, core_utils_1.percentToBps)(params.config.platformFeePercent));
193
204
  const withdrawAccount = (0, anchor_1.translateAddress)(params.config.withdrawAccount);
194
- const ix = await this.getInitializeStreamConfigInstruction(admin, {
205
+ const feeVault = (0, anchor_1.translateAddress)(params.config.feeVault);
206
+ const feeTiers = params.config.feeTiers.map((tier) => {
207
+ return {
208
+ 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)),
209
+ 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)),
210
+ fee: new anchor_1.BN((0, core_utils_1.percentToBps)(tier.feeRateInPercent)),
211
+ };
212
+ });
213
+ const ix = await this.getInitializeStreamConfigInstruction(admin, streamConfig, {
195
214
  baseFee,
196
215
  frequencies,
197
216
  platformFee,
198
217
  withdrawAccount,
218
+ feeTiers,
219
+ configName: params.config.configName,
220
+ feeVault,
199
221
  });
200
222
  return this._createPayload(admin, [ix]);
201
223
  }
@@ -204,15 +226,27 @@ class ZebecStreamService {
204
226
  if (!admin) {
205
227
  throw new Error("Either provide admin or create provider with public key");
206
228
  }
229
+ const [streamConfig] = (0, pda_1.deriveStreamConfigPda)(params.config.configName, this.programId);
207
230
  const baseFee = new anchor_1.BN((0, core_utils_1.percentToBps)(params.config.baseFeePercent));
208
231
  const frequencies = params.config.frequencies.map((frequency) => new anchor_1.BN(frequency));
209
232
  const platformFee = new anchor_1.BN((0, core_utils_1.percentToBps)(params.config.platformFeePercent));
210
233
  const withdrawAccount = (0, anchor_1.translateAddress)(params.config.withdrawAccount);
211
- const ix = await this.getUpdateStreamConfigInstruction(admin, {
234
+ const feeVault = (0, anchor_1.translateAddress)(params.config.feeVault);
235
+ const feeTiers = params.config.feeTiers.map((tier) => {
236
+ return {
237
+ 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)),
238
+ 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)),
239
+ fee: new anchor_1.BN((0, core_utils_1.percentToBps)(tier.feeRateInPercent)),
240
+ };
241
+ });
242
+ const ix = await this.getUpdateStreamConfigInstruction(admin, streamConfig, {
212
243
  baseFee,
213
244
  frequencies,
214
245
  platformFee,
215
246
  withdrawAccount,
247
+ feeTiers,
248
+ configName: params.config.configName,
249
+ feeVault,
216
250
  });
217
251
  return this._createPayload(admin, [ix]);
218
252
  }
@@ -221,7 +255,7 @@ class ZebecStreamService {
221
255
  const sender = (0, anchor_1.translateAddress)(params.sender);
222
256
  const feePayer = params.feePayer ? (0, anchor_1.translateAddress)(params.feePayer) : sender;
223
257
  const streamToken = (0, anchor_1.translateAddress)(params.streamToken);
224
- const [streamConfig] = (0, pda_1.deriveStreamConfigPda)(this.programId);
258
+ const [streamConfig] = (0, pda_1.deriveStreamConfigPda)(params.configName, this.programId);
225
259
  const streamConfigAccount = await this.program.account.streamConfig.fetch(streamConfig);
226
260
  const withdrawer = streamConfigAccount.withdrawAccount;
227
261
  const autoWithdrawFrequencies = new Set(Array.from(streamConfigAccount.frequencies.map((f) => f.toNumber())));
@@ -231,12 +265,35 @@ class ZebecStreamService {
231
265
  const senderAta = (0, solana_common_1.getAssociatedTokenAddressSync)(streamToken, sender, true);
232
266
  const streamMetadataKeypair = params.streamMetadataKeypair ?? web3_js_1.Keypair.generate();
233
267
  const streamTokenDecimals = await (0, solana_common_1.getMintDecimals)(this.connection, streamToken);
234
- const amount = new anchor_1.BN((0, bignumber_js_1.BigNumber)(params.amount).times(solana_common_1.TEN_BIGNUM.pow(streamTokenDecimals)).toFixed(0));
268
+ const amount = (0, bignumber_js_1.BigNumber)(params.amount).times(solana_common_1.TEN_BIGNUM.pow(streamTokenDecimals)).toFixed(0);
235
269
  const cliffPercentage = new anchor_1.BN((0, core_utils_1.percentToBps)(params.cliffPercentage));
236
270
  const streamName = new Uint8Array(constants_1.STREAM_NAME_BUFFER_SIZE);
237
271
  streamName.set(anchor_1.utils.bytes.utf8.encode(params.streamName));
238
- const ix = await this.getCreateStreamInstruction(feePayer, receiver, senderAta, streamToken, withdrawer, sender, streamMetadataKeypair.publicKey, {
239
- amount,
272
+ const configAccount = await this.program.account.streamConfig.fetch(streamConfig);
273
+ const feeTiers = configAccount.feeTiers.tiers.map((tier) => ({
274
+ feeRateInPercent: (0, core_utils_1.bpsToPercent)(tier.fee.toNumber()),
275
+ minThreshold: (0, bignumber_js_1.BigNumber)(tier.minAmount.toString()).div(solana_common_1.UNITS_PER_USDC).toFixed(),
276
+ maxThreshold: (0, bignumber_js_1.BigNumber)(tier.maxAmount.toString()).div(solana_common_1.UNITS_PER_USDC).toFixed(),
277
+ }));
278
+ const feeAmount = await (0, utils_1.calculateFeeTokenAmountForStream)(params.streamTokenSymbol, params.amount, params.feeTokenSymbol, feeTiers, this.network);
279
+ const feeToken = (0, anchor_1.translateAddress)(params.feeToken);
280
+ const feeTokenDecimals = await (0, solana_common_1.getMintDecimals)(this.connection, feeToken);
281
+ const parsedFeeAmount = (0, bignumber_js_1.BigNumber)(feeAmount).times(solana_common_1.TEN_BIGNUM.pow(feeTokenDecimals)).toFixed(0);
282
+ const feeVault = configAccount.feeVault;
283
+ const feeVaultAta = (0, solana_common_1.getAssociatedTokenAddressSync)(feeToken, feeVault, true);
284
+ const senderFeeTokenAta = (0, solana_common_1.getAssociatedTokenAddressSync)(feeToken, sender, true);
285
+ const feeVaultAtaInfo = await this.connection.getAccountInfo(feeVaultAta);
286
+ const ixs = [];
287
+ // add instruction to create fee vault ATA if it does not exist
288
+ if (!feeVaultAtaInfo) {
289
+ const createFeeVaultAtaIx = (0, solana_common_1.createAssociatedTokenAccountInstruction)(feePayer, feeVaultAta, feeVault, feeToken);
290
+ ixs.push(createFeeVaultAtaIx);
291
+ }
292
+ // add instruction to transfer fee to fee vault
293
+ const transferFeeToVaultIx = (0, spl_token_1.createTransferInstruction)(senderFeeTokenAta, feeVaultAta, sender, BigInt(parsedFeeAmount));
294
+ ixs.push(transferFeeToVaultIx);
295
+ const createStreamIx = await this.getCreateStreamInstruction(feePayer, receiver, senderAta, streamToken, withdrawer, sender, streamMetadataKeypair.publicKey, {
296
+ amount: new anchor_1.BN(amount),
240
297
  automaticWithdrawal: params.automaticWithdrawal,
241
298
  cancelableByRecipient: params.cancelableByRecipient,
242
299
  cancelableBySender: params.cancelableBySender,
@@ -252,7 +309,8 @@ class ZebecStreamService {
252
309
  transferableByRecipient: params.transferableByRecipient,
253
310
  transferableBySender: params.transferableBySender,
254
311
  });
255
- return this._createPayload(feePayer, [ix], [streamMetadataKeypair]);
312
+ ixs.push(createStreamIx);
313
+ return this._createPayload(feePayer, ixs, [streamMetadataKeypair]);
256
314
  }
257
315
  async cancelStream(params) {
258
316
  const user = (0, anchor_1.translateAddress)(params.user);
@@ -312,8 +370,8 @@ class ZebecStreamService {
312
370
  const ix = await this.getChangeStreamReceiverInstruction(streamMetadata, newRecipient, signer);
313
371
  return this._createPayload(signer, [ix]);
314
372
  }
315
- async getStreamConfigInfo(commitment) {
316
- const [config] = (0, pda_1.deriveStreamConfigPda)(this.programId);
373
+ async getStreamConfigInfo(configName, commitment) {
374
+ const [config] = (0, pda_1.deriveStreamConfigPda)(configName, this.programId);
317
375
  const configInfo = await this.program.account.streamConfig.fetch(config, commitment ?? this.connection.commitment);
318
376
  return {
319
377
  address: config,
@@ -323,10 +381,16 @@ class ZebecStreamService {
323
381
  platformFee: Number((0, core_utils_1.bpsToPercent)(configInfo.platformFee.toNumber())),
324
382
  baseFee: Number((0, core_utils_1.bpsToPercent)(configInfo.baseFee.toNumber())),
325
383
  frequencies: configInfo.frequencies.map((frequency) => frequency.toNumber()),
384
+ feeTiers: configInfo.feeTiers.tiers.map((tier) => ({
385
+ feeRateInPercent: (0, core_utils_1.bpsToPercent)(tier.fee.toNumber()),
386
+ minThreshold: (0, bignumber_js_1.BigNumber)(tier.minAmount.toString()).div(solana_common_1.UNITS_PER_USDC).toFixed(),
387
+ maxThreshold: (0, bignumber_js_1.BigNumber)(tier.maxAmount.toString()).div(solana_common_1.UNITS_PER_USDC).toFixed(),
388
+ })),
389
+ feeVault: configInfo.feeVault,
326
390
  };
327
391
  }
328
- async getWhitelistedTokens(commitment) {
329
- const [config] = (0, pda_1.deriveStreamConfigPda)(this.programId);
392
+ async getWhitelistedTokens(configName, commitment) {
393
+ const [config] = (0, pda_1.deriveStreamConfigPda)(configName, this.programId);
330
394
  const configInfo = await this.program.account.streamConfig.fetch(config, commitment ?? this.connection.commitment);
331
395
  const whitelistedTokens = configInfo.whitelistedTokens;
332
396
  const umi = (0, umi_bundle_defaults_1.createUmi)(this.connection.rpcEndpoint, commitment);
package/dist/types.d.ts CHANGED
@@ -1,4 +1,6 @@
1
- import { PublicKey } from "@solana/web3.js";
1
+ import type { Address } from "@coral-xyz/anchor";
2
+ import type { Keypair, PublicKey } from "@solana/web3.js";
3
+ export type RpcNetwork = "mainnet-beta" | "devnet";
2
4
  export type Numeric = string | number;
3
5
  export type StreamConfigInfo = {
4
6
  address: PublicKey;
@@ -8,6 +10,8 @@ export type StreamConfigInfo = {
8
10
  platformFee: number;
9
11
  baseFee: number;
10
12
  frequencies: number[];
13
+ feeTiers: FeeTier[];
14
+ feeVault: PublicKey;
11
15
  };
12
16
  export type StreamMetadataInfo = {
13
17
  address: PublicKey;
@@ -58,3 +62,81 @@ export type TokenMetadata = {
58
62
  uri: string;
59
63
  } | null;
60
64
  };
65
+ export type CreateStreamParams = {
66
+ configName: string;
67
+ feePayer?: Address;
68
+ receiver: Address;
69
+ sender: Address;
70
+ streamToken: Address;
71
+ streamTokenSymbol: string;
72
+ feeToken: Address;
73
+ feeTokenSymbol: string;
74
+ amount: Numeric;
75
+ automaticWithdrawal: boolean;
76
+ cancelableByRecipient: boolean;
77
+ cancelableBySender: boolean;
78
+ cliffPercentage: Numeric;
79
+ duration: number;
80
+ isPausable: boolean;
81
+ startNow: boolean;
82
+ startTime: number;
83
+ autoWithdrawFrequency: number;
84
+ streamName: string;
85
+ transferableByRecipient: boolean;
86
+ transferableBySender: boolean;
87
+ canTopup: boolean;
88
+ rateUpdatable: boolean;
89
+ streamMetadataKeypair?: Keypair;
90
+ };
91
+ export type InitializeStreamConfigParams = {
92
+ admin?: Address;
93
+ config: {
94
+ baseFeePercent: Numeric;
95
+ frequencies: number[];
96
+ platformFeePercent: Numeric;
97
+ withdrawAccount: Address;
98
+ configName: string;
99
+ feeTiers: FeeTier[];
100
+ feeVault: Address;
101
+ };
102
+ };
103
+ export type FeeTier = {
104
+ minThreshold: Numeric;
105
+ maxThreshold: Numeric;
106
+ feeRateInPercent: Numeric;
107
+ };
108
+ export type UpdateStreamConfigParams = {
109
+ admin?: Address;
110
+ config: {
111
+ baseFeePercent: Numeric;
112
+ frequencies: number[];
113
+ platformFeePercent: Numeric;
114
+ withdrawAccount: Address;
115
+ configName: string;
116
+ feeTiers: FeeTier[];
117
+ feeVault: Address;
118
+ };
119
+ };
120
+ export type CancelStreamParams = {
121
+ feePayer?: Address;
122
+ streamMetadata: Address;
123
+ user: Address;
124
+ };
125
+ export type PauseResumeStreamParams = {
126
+ streamMetadata: Address;
127
+ };
128
+ export type WithdrawStreamParams = {
129
+ streamMetadata: Address;
130
+ withdrawer?: Address;
131
+ feePayer?: Address;
132
+ receiver: Address;
133
+ };
134
+ export type WhiteListTokensParams = {
135
+ admin: Address;
136
+ tokens: Address[];
137
+ };
138
+ export type ChangeStreamReceiverParams = {
139
+ streamMetadata: Address;
140
+ newRecipient: Address;
141
+ signer: Address;
142
+ };
@@ -0,0 +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;
package/dist/utils.js ADDED
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getTokenUsdPrice = getTokenUsdPrice;
4
+ exports.calculateFeeTokenAmountForStream = calculateFeeTokenAmountForStream;
5
+ exports.getFeeRateForUsdAmount = getFeeRateForUsdAmount;
6
+ const core_utils_1 = require("@zebec-network/core-utils");
7
+ const constants_1 = require("./constants");
8
+ async function getTokenUsdPrice(tokenSymbol, network) {
9
+ const url = `${constants_1.SUPERAPP_BACKEND_URL[network]}/tokens/quotes/${encodeURIComponent(`${tokenSymbol}_USD`)}/1?type=EXACT_IN&chainName=SOLANA`;
10
+ const response = await fetch(url);
11
+ if (!response.ok) {
12
+ const body = await response.text().catch(() => "");
13
+ throw new Error(`Failed to fetch token price for symbol: ${tokenSymbol}, network: ${network}, status: ${response.status} ${body}`);
14
+ }
15
+ const data = await response.json();
16
+ if (!data || !("exchangeRate" in data)) {
17
+ console.debug("Unexpected response format when fetching token price:", data);
18
+ throw new Error(`Invalid response format when fetching token price for symbol: ${tokenSymbol}, network: ${network}`);
19
+ }
20
+ return Number(data.exchangeRate);
21
+ }
22
+ async function calculateFeeTokenAmountForStream(streamTokenSymbol, streamTokenAmount, feeTokenSymbol, feeTiers, network) {
23
+ const oneStreamTokenPriceInUsd = await getTokenUsdPrice(streamTokenSymbol, network);
24
+ const oneFeeTokenPriceInUsd = await getTokenUsdPrice(feeTokenSymbol, network);
25
+ if (oneFeeTokenPriceInUsd === 0) {
26
+ throw new Error(`Fee token price is zero for symbol: ${feeTokenSymbol}, network: ${network}`);
27
+ }
28
+ const streamTokenAmountUsdPrice = new BigNumber(streamTokenAmount).times(oneStreamTokenPriceInUsd);
29
+ const feeRateInBps = getFeeRateForUsdAmount(streamTokenAmountUsdPrice, feeTiers);
30
+ const feeAmountUsdPrice = streamTokenAmountUsdPrice.times(feeRateInBps).div(10000);
31
+ const feeTokenAmount = feeAmountUsdPrice.div(oneFeeTokenPriceInUsd);
32
+ return feeTokenAmount;
33
+ }
34
+ function getFeeRateForUsdAmount(amount, feeTiers) {
35
+ feeTiers.sort((a, b) => BigNumber(a.minThreshold).comparedTo(BigNumber(b.minThreshold)) ?? 0);
36
+ const tier = feeTiers.find((tier) => amount.gte(tier.minThreshold) && amount.lt(tier.maxThreshold));
37
+ if (!tier) {
38
+ throw new Error(`No fee tier found for amount: ${amount}`);
39
+ }
40
+ return (0, core_utils_1.percentToBps)(tier.feeRateInPercent);
41
+ }
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": "2.0.0"
43
+ "version": "3.0.0-dev.1"
44
44
  }