@ecency/sdk 1.3.6 → 1.3.9

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.
@@ -1,5 +1,5 @@
1
- import { QueryClient, useQuery, useInfiniteQuery, useMutation, queryOptions, useQueryClient, infiniteQueryOptions } from '@tanstack/react-query';
2
- import { Client, PrivateKey, cryptoUtils, RCAPI } from '@hiveio/dhive';
1
+ import { QueryClient, useQuery, useInfiniteQuery, useMutation, queryOptions, infiniteQueryOptions, useQueryClient } from '@tanstack/react-query';
2
+ import { Client, utils, PrivateKey, cryptoUtils, RCAPI } from '@hiveio/dhive';
3
3
  import hs from 'hivesigner';
4
4
  import * as R4 from 'remeda';
5
5
 
@@ -55,7 +55,16 @@ var CONFIG = {
55
55
  heliusApiKey: process.env.VITE_HELIUS_API_KEY,
56
56
  queryClient: new QueryClient(),
57
57
  plausibleHost: "https://pl.ecency.com",
58
- spkNode: "https://spk.good-karma.xyz"
58
+ spkNode: "https://spk.good-karma.xyz",
59
+ // DMCA filtering - can be configured by the app
60
+ dmcaAccounts: [],
61
+ dmcaTags: [],
62
+ dmcaPatterns: [],
63
+ // Pre-compiled regex patterns for performance and security
64
+ dmcaTagRegexes: [],
65
+ dmcaPatternRegexes: [],
66
+ // Track if DMCA has been initialized to avoid duplicate logs
67
+ _dmcaInitialized: false
59
68
  };
60
69
  var ConfigManager;
61
70
  ((ConfigManager2) => {
@@ -63,6 +72,115 @@ var ConfigManager;
63
72
  CONFIG.queryClient = client;
64
73
  }
65
74
  ConfigManager2.setQueryClient = setQueryClient;
75
+ function setPrivateApiHost(host) {
76
+ CONFIG.privateApiHost = host;
77
+ }
78
+ ConfigManager2.setPrivateApiHost = setPrivateApiHost;
79
+ function analyzeRedosRisk(pattern) {
80
+ if (/(\([^)]*[*+{][^)]*\))[*+{]/.test(pattern)) {
81
+ return { safe: false, reason: "nested quantifiers detected" };
82
+ }
83
+ if (/\([^|)]*\|[^)]*\)[*+{]/.test(pattern)) {
84
+ return { safe: false, reason: "alternation with quantifier (potential overlap)" };
85
+ }
86
+ if (/\([^)]*[*+][^)]*\)[*+]/.test(pattern)) {
87
+ return { safe: false, reason: "repeated quantifiers (catastrophic backtracking risk)" };
88
+ }
89
+ if (/\.\*\.\*/.test(pattern) || /\.\+\.\+/.test(pattern)) {
90
+ return { safe: false, reason: "multiple greedy quantifiers on wildcards" };
91
+ }
92
+ const unboundedRange = /\.?\{(\d+),(\d+)\}/g;
93
+ let match;
94
+ while ((match = unboundedRange.exec(pattern)) !== null) {
95
+ const [, min, max] = match;
96
+ const range = parseInt(max, 10) - parseInt(min, 10);
97
+ if (range > 1e3) {
98
+ return { safe: false, reason: `excessive range: {${min},${max}}` };
99
+ }
100
+ }
101
+ return { safe: true };
102
+ }
103
+ function testRegexPerformance(regex) {
104
+ const adversarialInputs = [
105
+ // Nested quantifier attack
106
+ "a".repeat(50) + "x",
107
+ // Alternation attack
108
+ "ab".repeat(50) + "x",
109
+ // Wildcard attack
110
+ "x".repeat(100),
111
+ // Mixed attack
112
+ "aaa".repeat(30) + "bbb".repeat(30) + "x"
113
+ ];
114
+ const maxExecutionTime = 5;
115
+ for (const input of adversarialInputs) {
116
+ const start = Date.now();
117
+ try {
118
+ regex.test(input);
119
+ const duration = Date.now() - start;
120
+ if (duration > maxExecutionTime) {
121
+ return {
122
+ safe: false,
123
+ reason: `runtime test exceeded ${maxExecutionTime}ms (took ${duration}ms on input length ${input.length})`
124
+ };
125
+ }
126
+ } catch (err) {
127
+ return { safe: false, reason: `runtime test threw error: ${err}` };
128
+ }
129
+ }
130
+ return { safe: true };
131
+ }
132
+ function safeCompileRegex(pattern, maxLength = 200) {
133
+ try {
134
+ if (!pattern) {
135
+ console.warn(`[SDK] DMCA pattern rejected: empty pattern`);
136
+ return null;
137
+ }
138
+ if (pattern.length > maxLength) {
139
+ console.warn(`[SDK] DMCA pattern rejected: length ${pattern.length} exceeds max ${maxLength} - pattern: ${pattern.substring(0, 50)}...`);
140
+ return null;
141
+ }
142
+ const staticAnalysis = analyzeRedosRisk(pattern);
143
+ if (!staticAnalysis.safe) {
144
+ console.warn(`[SDK] DMCA pattern rejected: static analysis failed (${staticAnalysis.reason}) - pattern: ${pattern.substring(0, 50)}...`);
145
+ return null;
146
+ }
147
+ let regex;
148
+ try {
149
+ regex = new RegExp(pattern);
150
+ } catch (compileErr) {
151
+ console.warn(`[SDK] DMCA pattern rejected: compilation failed - pattern: ${pattern.substring(0, 50)}...`, compileErr);
152
+ return null;
153
+ }
154
+ const runtimeTest = testRegexPerformance(regex);
155
+ if (!runtimeTest.safe) {
156
+ console.warn(`[SDK] DMCA pattern rejected: runtime test failed (${runtimeTest.reason}) - pattern: ${pattern.substring(0, 50)}...`);
157
+ return null;
158
+ }
159
+ return regex;
160
+ } catch (err) {
161
+ console.warn(`[SDK] DMCA pattern rejected: unexpected error - pattern: ${pattern.substring(0, 50)}...`, err);
162
+ return null;
163
+ }
164
+ }
165
+ function setDmcaLists(accounts = [], tags = [], patterns = []) {
166
+ CONFIG.dmcaAccounts = accounts;
167
+ CONFIG.dmcaTags = tags;
168
+ CONFIG.dmcaPatterns = patterns;
169
+ CONFIG.dmcaTagRegexes = tags.map((pattern) => safeCompileRegex(pattern)).filter((r) => r !== null);
170
+ CONFIG.dmcaPatternRegexes = [];
171
+ const rejectedTagCount = tags.length - CONFIG.dmcaTagRegexes.length;
172
+ if (!CONFIG._dmcaInitialized) {
173
+ console.log(`[SDK] DMCA configuration loaded:`);
174
+ console.log(` - Accounts: ${accounts.length}`);
175
+ console.log(` - Tag patterns: ${CONFIG.dmcaTagRegexes.length}/${tags.length} compiled (${rejectedTagCount} rejected)`);
176
+ console.log(` - Post patterns: ${patterns.length} (using exact string matching)`);
177
+ if (rejectedTagCount > 0) {
178
+ console.warn(`[SDK] ${rejectedTagCount} DMCA tag patterns were rejected due to security validation. Check warnings above for details.`);
179
+ }
180
+ CONFIG._dmcaInitialized = true;
181
+ }
182
+ }
183
+ ConfigManager2.setDmcaLists = setDmcaLists;
66
184
  })(ConfigManager || (ConfigManager = {}));
67
185
 
68
186
  // src/modules/core/utils/decoder-encoder.ts
@@ -468,6 +586,176 @@ function getAccountFullQueryOptions(username) {
468
586
  staleTime: 6e4
469
587
  });
470
588
  }
589
+ function sanitizeTokens(tokens) {
590
+ return tokens?.map(({ meta, ...rest }) => {
591
+ if (!meta || typeof meta !== "object") {
592
+ return { ...rest, meta };
593
+ }
594
+ const { privateKey, username, ...safeMeta } = meta;
595
+ return { ...rest, meta: safeMeta };
596
+ });
597
+ }
598
+ function parseProfileMetadata(postingJsonMetadata) {
599
+ if (!postingJsonMetadata) {
600
+ return {};
601
+ }
602
+ try {
603
+ const parsed = JSON.parse(postingJsonMetadata);
604
+ if (parsed && typeof parsed === "object" && parsed.profile && typeof parsed.profile === "object") {
605
+ return parsed.profile;
606
+ }
607
+ } catch (err) {
608
+ }
609
+ return {};
610
+ }
611
+ function extractAccountProfile(data) {
612
+ return parseProfileMetadata(data?.posting_json_metadata);
613
+ }
614
+ function buildProfileMetadata({
615
+ existingProfile,
616
+ profile,
617
+ tokens
618
+ }) {
619
+ const { tokens: profileTokens, version: _ignoredVersion, ...profileRest } = profile ?? {};
620
+ const metadata = R4.mergeDeep(
621
+ existingProfile ?? {},
622
+ profileRest
623
+ );
624
+ const nextTokens = tokens ?? profileTokens;
625
+ if (nextTokens && nextTokens.length > 0) {
626
+ metadata.tokens = nextTokens;
627
+ }
628
+ metadata.tokens = sanitizeTokens(metadata.tokens);
629
+ metadata.version = 2;
630
+ return metadata;
631
+ }
632
+
633
+ // src/modules/accounts/utils/parse-accounts.ts
634
+ function parseAccounts(rawAccounts) {
635
+ return rawAccounts.map((x) => {
636
+ const account = {
637
+ name: x.name,
638
+ owner: x.owner,
639
+ active: x.active,
640
+ posting: x.posting,
641
+ memo_key: x.memo_key,
642
+ post_count: x.post_count,
643
+ created: x.created,
644
+ reputation: x.reputation,
645
+ posting_json_metadata: x.posting_json_metadata,
646
+ last_vote_time: x.last_vote_time,
647
+ last_post: x.last_post,
648
+ json_metadata: x.json_metadata,
649
+ reward_hive_balance: x.reward_hive_balance,
650
+ reward_hbd_balance: x.reward_hbd_balance,
651
+ reward_vesting_hive: x.reward_vesting_hive,
652
+ reward_vesting_balance: x.reward_vesting_balance,
653
+ balance: x.balance,
654
+ hbd_balance: x.hbd_balance,
655
+ savings_balance: x.savings_balance,
656
+ savings_hbd_balance: x.savings_hbd_balance,
657
+ savings_hbd_last_interest_payment: x.savings_hbd_last_interest_payment,
658
+ savings_hbd_seconds_last_update: x.savings_hbd_seconds_last_update,
659
+ savings_hbd_seconds: x.savings_hbd_seconds,
660
+ next_vesting_withdrawal: x.next_vesting_withdrawal,
661
+ pending_claimed_accounts: x.pending_claimed_accounts,
662
+ vesting_shares: x.vesting_shares,
663
+ delegated_vesting_shares: x.delegated_vesting_shares,
664
+ received_vesting_shares: x.received_vesting_shares,
665
+ vesting_withdraw_rate: x.vesting_withdraw_rate,
666
+ to_withdraw: x.to_withdraw,
667
+ withdrawn: x.withdrawn,
668
+ witness_votes: x.witness_votes,
669
+ proxy: x.proxy,
670
+ recovery_account: x.recovery_account,
671
+ proxied_vsf_votes: x.proxied_vsf_votes,
672
+ voting_manabar: x.voting_manabar,
673
+ voting_power: x.voting_power,
674
+ downvote_manabar: x.downvote_manabar
675
+ };
676
+ let profile = parseProfileMetadata(
677
+ x.posting_json_metadata
678
+ );
679
+ if (!profile || Object.keys(profile).length === 0) {
680
+ try {
681
+ const jsonMetadata = JSON.parse(x.json_metadata || "{}");
682
+ if (jsonMetadata.profile) {
683
+ profile = jsonMetadata.profile;
684
+ }
685
+ } catch (e) {
686
+ }
687
+ }
688
+ if (!profile || Object.keys(profile).length === 0) {
689
+ profile = {
690
+ about: "",
691
+ cover_image: "",
692
+ location: "",
693
+ name: "",
694
+ profile_image: "",
695
+ website: ""
696
+ };
697
+ }
698
+ return { ...account, profile };
699
+ });
700
+ }
701
+
702
+ // src/modules/accounts/queries/get-accounts-query-options.ts
703
+ function getAccountsQueryOptions(usernames) {
704
+ return queryOptions({
705
+ queryKey: ["accounts", "get-accounts", usernames],
706
+ queryFn: async () => {
707
+ const response = await CONFIG.hiveClient.database.getAccounts(usernames);
708
+ return parseAccounts(response);
709
+ },
710
+ enabled: usernames.length > 0
711
+ });
712
+ }
713
+ function getFollowCountQueryOptions(username) {
714
+ return queryOptions({
715
+ queryKey: ["accounts", "follow-count", username],
716
+ queryFn: () => CONFIG.hiveClient.database.call("get_follow_count", [
717
+ username
718
+ ])
719
+ });
720
+ }
721
+ function getFollowingQueryOptions(follower, startFollowing, followType = "blog", limit = 100) {
722
+ return queryOptions({
723
+ queryKey: ["accounts", "following", follower, startFollowing, followType, limit],
724
+ queryFn: () => CONFIG.hiveClient.database.call("get_following", [
725
+ follower,
726
+ startFollowing,
727
+ followType,
728
+ limit
729
+ ]),
730
+ enabled: !!follower
731
+ });
732
+ }
733
+ function getMutedUsersQueryOptions(username, limit = 100) {
734
+ return queryOptions({
735
+ queryKey: ["accounts", "muted-users", username],
736
+ queryFn: async () => {
737
+ const response = await CONFIG.hiveClient.database.call("get_following", [
738
+ username,
739
+ "",
740
+ "ignore",
741
+ limit
742
+ ]);
743
+ return response.map((user) => user.following);
744
+ },
745
+ enabled: !!username
746
+ });
747
+ }
748
+ function lookupAccountsQueryOptions(query, limit = 50) {
749
+ return queryOptions({
750
+ queryKey: ["accounts", "lookup", query, limit],
751
+ queryFn: () => CONFIG.hiveClient.database.call("lookup_accounts", [
752
+ query,
753
+ limit
754
+ ]),
755
+ enabled: !!query,
756
+ staleTime: Infinity
757
+ });
758
+ }
471
759
  function getSearchAccountsByUsernameQueryOptions(query, limit = 5, excludeList = []) {
472
760
  return queryOptions({
473
761
  queryKey: ["accounts", "search", query, excludeList],
@@ -687,314 +975,1320 @@ function getAccountPendingRecoveryQueryOptions(username) {
687
975
  )
688
976
  });
689
977
  }
690
- function sanitizeTokens(tokens) {
691
- return tokens?.map(({ meta, ...rest }) => {
692
- if (!meta || typeof meta !== "object") {
693
- return { ...rest, meta };
694
- }
695
- const { privateKey, username, ...safeMeta } = meta;
696
- return { ...rest, meta: safeMeta };
978
+ var ops = utils.operationOrders;
979
+ var ACCOUNT_OPERATION_GROUPS = {
980
+ transfers: [
981
+ ops.transfer,
982
+ ops.transfer_to_savings,
983
+ ops.transfer_from_savings,
984
+ ops.cancel_transfer_from_savings,
985
+ ops.recurrent_transfer,
986
+ ops.fill_recurrent_transfer,
987
+ ops.escrow_transfer,
988
+ ops.fill_recurrent_transfer
989
+ ],
990
+ "market-orders": [
991
+ ops.fill_convert_request,
992
+ ops.fill_order,
993
+ ops.fill_collateralized_convert_request,
994
+ ops.limit_order_create2,
995
+ ops.limit_order_create,
996
+ ops.limit_order_cancel
997
+ ],
998
+ interests: [ops.interest],
999
+ "stake-operations": [
1000
+ ops.return_vesting_delegation,
1001
+ ops.withdraw_vesting,
1002
+ ops.transfer_to_vesting,
1003
+ ops.set_withdraw_vesting_route,
1004
+ ops.update_proposal_votes,
1005
+ ops.fill_vesting_withdraw,
1006
+ ops.account_witness_proxy,
1007
+ ops.delegate_vesting_shares
1008
+ ],
1009
+ rewards: [
1010
+ ops.author_reward,
1011
+ ops.curation_reward,
1012
+ ops.producer_reward,
1013
+ ops.claim_reward_balance,
1014
+ ops.comment_benefactor_reward,
1015
+ ops.liquidity_reward,
1016
+ ops.proposal_pay
1017
+ ]
1018
+ };
1019
+ var ALL_ACCOUNT_OPERATIONS = [...Object.values(ACCOUNT_OPERATION_GROUPS)].reduce(
1020
+ (acc, val) => acc.concat(val),
1021
+ []
1022
+ );
1023
+ function getTransactionsInfiniteQueryOptions(username, limit = 20, group = "") {
1024
+ return infiniteQueryOptions({
1025
+ queryKey: ["accounts", "transactions", username ?? "", group, limit],
1026
+ initialPageParam: -1,
1027
+ queryFn: async ({ pageParam }) => {
1028
+ if (!username) {
1029
+ return [];
1030
+ }
1031
+ let filters;
1032
+ switch (group) {
1033
+ case "transfers":
1034
+ filters = utils.makeBitMaskFilter(ACCOUNT_OPERATION_GROUPS["transfers"]);
1035
+ break;
1036
+ case "market-orders":
1037
+ filters = utils.makeBitMaskFilter(ACCOUNT_OPERATION_GROUPS["market-orders"]);
1038
+ break;
1039
+ case "interests":
1040
+ filters = utils.makeBitMaskFilter(ACCOUNT_OPERATION_GROUPS["interests"]);
1041
+ break;
1042
+ case "stake-operations":
1043
+ filters = utils.makeBitMaskFilter(ACCOUNT_OPERATION_GROUPS["stake-operations"]);
1044
+ break;
1045
+ case "rewards":
1046
+ filters = utils.makeBitMaskFilter(ACCOUNT_OPERATION_GROUPS["rewards"]);
1047
+ break;
1048
+ default:
1049
+ filters = utils.makeBitMaskFilter(ALL_ACCOUNT_OPERATIONS);
1050
+ }
1051
+ const response = await (filters ? CONFIG.hiveClient.call("condenser_api", "get_account_history", [
1052
+ username,
1053
+ pageParam,
1054
+ limit,
1055
+ ...filters
1056
+ ]) : CONFIG.hiveClient.call("condenser_api", "get_account_history", [
1057
+ username,
1058
+ pageParam,
1059
+ limit
1060
+ ]));
1061
+ const mapped = response.map(([num, operation]) => {
1062
+ const base = {
1063
+ num,
1064
+ type: operation.op[0],
1065
+ timestamp: operation.timestamp,
1066
+ trx_id: operation.trx_id
1067
+ };
1068
+ const payload = operation.op[1];
1069
+ return { ...base, ...payload };
1070
+ }).filter(Boolean).sort((a, b) => b.num - a.num);
1071
+ return mapped;
1072
+ },
1073
+ getNextPageParam: (lastPage) => lastPage?.length ? (lastPage[lastPage.length - 1]?.num ?? 0) - 1 : -1
697
1074
  });
698
1075
  }
699
- function parseProfileMetadata(postingJsonMetadata) {
700
- if (!postingJsonMetadata) {
701
- return {};
702
- }
703
- try {
704
- const parsed = JSON.parse(postingJsonMetadata);
705
- if (parsed && typeof parsed === "object" && parsed.profile && typeof parsed.profile === "object") {
706
- return parsed.profile;
707
- }
708
- } catch (err) {
709
- }
710
- return {};
711
- }
712
- function extractAccountProfile(data) {
713
- return parseProfileMetadata(data?.posting_json_metadata);
714
- }
715
- function buildProfileMetadata({
716
- existingProfile,
717
- profile,
718
- tokens
719
- }) {
720
- const { tokens: profileTokens, version: _ignoredVersion, ...profileRest } = profile ?? {};
721
- const metadata = R4.mergeDeep(
722
- existingProfile ?? {},
723
- profileRest
724
- );
725
- const nextTokens = tokens ?? profileTokens;
726
- if (nextTokens && nextTokens.length > 0) {
727
- metadata.tokens = nextTokens;
728
- }
729
- metadata.tokens = sanitizeTokens(metadata.tokens);
730
- metadata.version = 2;
731
- return metadata;
1076
+ function getBotsQueryOptions() {
1077
+ return queryOptions({
1078
+ queryKey: ["accounts", "bots"],
1079
+ queryFn: async () => {
1080
+ const response = await fetch(CONFIG.privateApiHost + "/private-api/public/bots", {
1081
+ method: "GET",
1082
+ headers: {
1083
+ "Content-Type": "application/json"
1084
+ }
1085
+ });
1086
+ if (!response.ok) {
1087
+ throw new Error(`Failed to fetch bots: ${response.status}`);
1088
+ }
1089
+ return response.json();
1090
+ },
1091
+ refetchOnMount: true,
1092
+ staleTime: Infinity
1093
+ });
732
1094
  }
733
-
734
- // src/modules/accounts/mutations/use-account-update.ts
735
- function useAccountUpdate(username) {
736
- const queryClient = useQueryClient();
737
- const { data } = useQuery(getAccountFullQueryOptions(username));
738
- return useBroadcastMutation(
739
- ["accounts", "update"],
740
- username,
741
- (payload) => {
742
- if (!data) {
743
- throw new Error("[SDK][Accounts] \u2013 cannot update not existing account");
1095
+ function getReferralsInfiniteQueryOptions(username) {
1096
+ return infiniteQueryOptions({
1097
+ queryKey: ["accounts", "referrals", username],
1098
+ initialPageParam: { maxId: void 0 },
1099
+ queryFn: async ({ pageParam }) => {
1100
+ const { maxId } = pageParam ?? {};
1101
+ const url = new URL(CONFIG.privateApiHost + `/private-api/referrals/${username}`);
1102
+ if (maxId !== void 0) {
1103
+ url.searchParams.set("max_id", maxId.toString());
744
1104
  }
745
- const profile = buildProfileMetadata({
746
- existingProfile: extractAccountProfile(data),
747
- profile: payload.profile,
748
- tokens: payload.tokens
1105
+ const response = await fetch(url.toString(), {
1106
+ method: "GET",
1107
+ headers: {
1108
+ "Content-Type": "application/json"
1109
+ }
749
1110
  });
750
- return [
751
- [
752
- "account_update2",
753
- {
754
- account: username,
755
- json_metadata: "",
756
- extensions: [],
757
- posting_json_metadata: JSON.stringify({
758
- profile
759
- })
760
- }
761
- ]
762
- ];
1111
+ if (!response.ok) {
1112
+ throw new Error(`Failed to fetch referrals: ${response.status}`);
1113
+ }
1114
+ return response.json();
763
1115
  },
764
- (_, variables) => queryClient.setQueryData(
765
- getAccountFullQueryOptions(username).queryKey,
766
- (data2) => {
767
- if (!data2) {
768
- return data2;
1116
+ getNextPageParam: (lastPage) => {
1117
+ const nextMaxId = lastPage?.[lastPage.length - 1]?.id;
1118
+ return typeof nextMaxId === "number" ? { maxId: nextMaxId } : void 0;
1119
+ }
1120
+ });
1121
+ }
1122
+ function getReferralsStatsQueryOptions(username) {
1123
+ return queryOptions({
1124
+ queryKey: ["accounts", "referrals-stats", username],
1125
+ queryFn: async () => {
1126
+ const response = await fetch(
1127
+ CONFIG.privateApiHost + `/private-api/referrals/${username}/stats`,
1128
+ {
1129
+ method: "GET",
1130
+ headers: {
1131
+ "Content-Type": "application/json"
1132
+ }
769
1133
  }
770
- const obj = R4.clone(data2);
771
- obj.profile = buildProfileMetadata({
772
- existingProfile: extractAccountProfile(data2),
773
- profile: variables.profile,
774
- tokens: variables.tokens
775
- });
776
- return obj;
1134
+ );
1135
+ if (!response.ok) {
1136
+ throw new Error(`Failed to fetch referral stats: ${response.status}`);
777
1137
  }
778
- )
779
- );
1138
+ const data = await response.json();
1139
+ if (!data) {
1140
+ throw new Error("No Referrals for this user!");
1141
+ }
1142
+ return {
1143
+ total: data.total ?? 0,
1144
+ rewarded: data.rewarded ?? 0
1145
+ };
1146
+ }
1147
+ });
780
1148
  }
781
- function useAccountRelationsUpdate(reference, target, onSuccess, onError) {
782
- return useMutation({
783
- mutationKey: ["accounts", "relation", "update", reference, target],
784
- mutationFn: async (kind) => {
785
- const relationsQuery = getRelationshipBetweenAccountsQueryOptions(
786
- reference,
787
- target
1149
+ function getFriendsInfiniteQueryOptions(following, mode, options) {
1150
+ const { followType = "blog", limit = 100, enabled = true } = options ?? {};
1151
+ return infiniteQueryOptions({
1152
+ queryKey: ["accounts", "friends", following, mode, followType, limit],
1153
+ initialPageParam: { startFollowing: "" },
1154
+ enabled,
1155
+ refetchOnMount: true,
1156
+ queryFn: async ({ pageParam }) => {
1157
+ const { startFollowing } = pageParam;
1158
+ const response = await CONFIG.hiveClient.database.call(
1159
+ mode === "following" ? "get_following" : "get_followers",
1160
+ [following, startFollowing === "" ? null : startFollowing, followType, limit]
788
1161
  );
789
- await getQueryClient().prefetchQuery(relationsQuery);
790
- const actualRelation = getQueryClient().getQueryData(
791
- relationsQuery.queryKey
1162
+ const accountNames = response.map(
1163
+ (e) => mode === "following" ? e.following : e.follower
792
1164
  );
793
- await broadcastJson(reference, "follow", [
794
- "follow",
795
- {
796
- follower: reference,
797
- following: target,
798
- what: [
799
- ...kind === "toggle-ignore" && !actualRelation?.ignores ? ["ignore"] : [],
800
- ...kind === "toggle-follow" && !actualRelation?.follows ? ["blog"] : []
801
- ]
802
- }
803
- ]);
804
- return {
805
- ...actualRelation,
806
- ignores: kind === "toggle-ignore" ? !actualRelation?.ignores : actualRelation?.ignores,
807
- follows: kind === "toggle-follow" ? !actualRelation?.follows : actualRelation?.follows
808
- };
1165
+ const accounts = await CONFIG.hiveClient.call("bridge", "get_profiles", {
1166
+ accounts: accountNames,
1167
+ observer: void 0
1168
+ });
1169
+ const rows = (accounts ?? []).map((a) => ({
1170
+ name: a.name,
1171
+ reputation: a.reputation,
1172
+ active: a.active
1173
+ // Return raw timestamp
1174
+ }));
1175
+ return rows;
809
1176
  },
810
- onError,
811
- onSuccess(data) {
812
- onSuccess(data);
813
- getQueryClient().setQueryData(
814
- ["accounts", "relations", reference, target],
815
- data
1177
+ getNextPageParam: (lastPage) => lastPage && lastPage.length === limit ? { startFollowing: lastPage[lastPage.length - 1].name } : void 0
1178
+ });
1179
+ }
1180
+ var SEARCH_LIMIT = 30;
1181
+ function getSearchFriendsQueryOptions(username, mode, query) {
1182
+ return queryOptions({
1183
+ queryKey: ["accounts", "friends", "search", username, mode, query],
1184
+ refetchOnMount: false,
1185
+ enabled: false,
1186
+ // Manual query via refetch
1187
+ queryFn: async () => {
1188
+ if (!query) return [];
1189
+ const start = query.slice(0, -1);
1190
+ const response = await CONFIG.hiveClient.database.call(
1191
+ mode === "following" ? "get_following" : "get_followers",
1192
+ [username, start, "blog", 1e3]
816
1193
  );
1194
+ const accountNames = response.map((e) => mode === "following" ? e.following : e.follower).filter((name) => name.toLowerCase().includes(query.toLowerCase())).slice(0, SEARCH_LIMIT);
1195
+ const accounts = await CONFIG.hiveClient.call("bridge", "get_profiles", {
1196
+ accounts: accountNames,
1197
+ observer: void 0
1198
+ });
1199
+ return accounts?.map((a) => ({
1200
+ name: a.name,
1201
+ full_name: a.metadata.profile?.name || "",
1202
+ reputation: a.reputation,
1203
+ active: a.active
1204
+ // Return raw timestamp
1205
+ })) ?? [];
817
1206
  }
818
1207
  });
819
1208
  }
820
- function useBookmarkAdd(username, onSuccess, onError) {
821
- return useMutation({
822
- mutationKey: ["accounts", "bookmarks", "add", username],
823
- mutationFn: async ({ author, permlink }) => {
824
- if (!username) {
825
- throw new Error("[SDK][Account][Bookmarks] \u2013 no active user");
826
- }
1209
+ function getTrendingTagsQueryOptions(limit = 20) {
1210
+ return infiniteQueryOptions({
1211
+ queryKey: ["posts", "trending-tags"],
1212
+ queryFn: async ({ pageParam: { afterTag } }) => CONFIG.hiveClient.database.call("get_trending_tags", [afterTag, limit]).then(
1213
+ (tags) => tags.filter((x) => x.name !== "").filter((x) => !x.name.startsWith("hive-")).map((x) => x.name)
1214
+ ),
1215
+ initialPageParam: { afterTag: "" },
1216
+ getNextPageParam: (lastPage) => ({
1217
+ afterTag: lastPage?.[lastPage?.length - 1]
1218
+ }),
1219
+ staleTime: Infinity,
1220
+ refetchOnMount: true
1221
+ });
1222
+ }
1223
+ function getFragmentsQueryOptions(username) {
1224
+ return queryOptions({
1225
+ queryKey: ["posts", "fragments", username],
1226
+ queryFn: async () => {
827
1227
  const fetchApi = getBoundFetch();
828
1228
  const response = await fetchApi(
829
- CONFIG.privateApiHost + "/private-api/bookmarks-add",
1229
+ CONFIG.privateApiHost + "/private-api/fragments",
830
1230
  {
831
1231
  method: "POST",
832
- headers: {
833
- "Content-Type": "application/json"
834
- },
835
1232
  body: JSON.stringify({
836
- author,
837
- permlink,
838
1233
  code: getAccessToken(username)
839
- })
1234
+ }),
1235
+ headers: {
1236
+ "Content-Type": "application/json"
1237
+ }
840
1238
  }
841
1239
  );
842
1240
  return response.json();
843
1241
  },
844
- onSuccess: () => {
845
- onSuccess();
846
- getQueryClient().invalidateQueries({
847
- queryKey: ["accounts", "bookmarks", username]
848
- });
849
- },
850
- onError
1242
+ enabled: !!username
851
1243
  });
852
1244
  }
853
- function useBookmarkDelete(username, onSuccess, onError) {
854
- return useMutation({
855
- mutationKey: ["accounts", "bookmarks", "delete", username],
856
- mutationFn: async (bookmarkId) => {
857
- if (!username) {
858
- throw new Error("[SDK][Account][Bookmarks] \u2013 no active user");
1245
+ function getPromotedPostsQuery(type = "feed") {
1246
+ return queryOptions({
1247
+ queryKey: ["posts", "promoted", type],
1248
+ queryFn: async () => {
1249
+ const url = new URL(
1250
+ CONFIG.privateApiHost + "/private-api/promoted-entries"
1251
+ );
1252
+ if (type === "waves") {
1253
+ url.searchParams.append("short_content", "1");
859
1254
  }
860
1255
  const fetchApi = getBoundFetch();
861
- const response = await fetchApi(
862
- CONFIG.privateApiHost + "/private-api/bookmarks-delete",
863
- {
864
- method: "POST",
865
- headers: {
866
- "Content-Type": "application/json"
867
- },
868
- body: JSON.stringify({
869
- id: bookmarkId,
870
- code: getAccessToken(username)
871
- })
1256
+ const response = await fetchApi(url.toString(), {
1257
+ method: "GET",
1258
+ headers: {
1259
+ "Content-Type": "application/json"
872
1260
  }
873
- );
874
- return response.json();
1261
+ });
1262
+ const data = await response.json();
1263
+ return data;
1264
+ }
1265
+ });
1266
+ }
1267
+ function getEntryActiveVotesQueryOptions(entry) {
1268
+ return queryOptions({
1269
+ queryKey: ["posts", "entry-active-votes", entry?.author, entry?.permlink],
1270
+ queryFn: async () => {
1271
+ return CONFIG.hiveClient.database.call("get_active_votes", [
1272
+ entry?.author,
1273
+ entry?.permlink
1274
+ ]);
875
1275
  },
876
- onSuccess: () => {
877
- onSuccess();
878
- getQueryClient().invalidateQueries({
879
- queryKey: ["accounts", "bookmarks", username]
1276
+ enabled: !!entry
1277
+ });
1278
+ }
1279
+ function getPostHeaderQueryOptions(author, permlink) {
1280
+ return queryOptions({
1281
+ queryKey: ["posts", "post-header", author, permlink],
1282
+ queryFn: async () => {
1283
+ return CONFIG.hiveClient.call("bridge", "get_post_header", {
1284
+ author,
1285
+ permlink
880
1286
  });
881
1287
  },
882
- onError
1288
+ initialData: null
883
1289
  });
884
1290
  }
885
- function useAccountFavouriteAdd(username, onSuccess, onError) {
886
- return useMutation({
887
- mutationKey: ["accounts", "favourites", "add", username],
888
- mutationFn: async (account) => {
889
- if (!username) {
890
- throw new Error("[SDK][Account][Bookmarks] \u2013 no active user");
1291
+
1292
+ // src/modules/posts/utils/filter-dmca-entries.ts
1293
+ function filterDmcaEntry(entryOrEntries) {
1294
+ if (Array.isArray(entryOrEntries)) {
1295
+ return entryOrEntries.map((entry) => applyFilter(entry));
1296
+ }
1297
+ return applyFilter(entryOrEntries);
1298
+ }
1299
+ function applyFilter(entry) {
1300
+ if (!entry) return entry;
1301
+ const entryPath = `@${entry.author}/${entry.permlink}`;
1302
+ const isDmca = CONFIG.dmcaPatternRegexes.some((regex) => regex.test(entryPath));
1303
+ if (isDmca) {
1304
+ return {
1305
+ ...entry,
1306
+ body: "This post is not available due to a copyright/fraudulent claim.",
1307
+ title: ""
1308
+ };
1309
+ }
1310
+ return entry;
1311
+ }
1312
+
1313
+ // src/modules/posts/queries/get-post-query-options.ts
1314
+ function makeEntryPath(category, author, permlink) {
1315
+ return `${category}/@${author}/${permlink}`;
1316
+ }
1317
+ function getPostQueryOptions(author, permlink, observer = "", num) {
1318
+ const cleanPermlink = permlink?.trim();
1319
+ const entryPath = makeEntryPath("", author, cleanPermlink ?? "");
1320
+ return queryOptions({
1321
+ queryKey: ["posts", "entry", entryPath],
1322
+ queryFn: async () => {
1323
+ if (!cleanPermlink || cleanPermlink === "undefined") {
1324
+ return null;
891
1325
  }
892
- const fetchApi = getBoundFetch();
893
- const response = await fetchApi(
894
- CONFIG.privateApiHost + "/private-api/favorites-add",
895
- {
896
- method: "POST",
897
- headers: {
898
- "Content-Type": "application/json"
899
- },
900
- body: JSON.stringify({
901
- account,
902
- code: getAccessToken(username)
903
- })
904
- }
905
- );
906
- return response.json();
907
- },
908
- onSuccess: () => {
909
- onSuccess();
910
- getQueryClient().invalidateQueries({
911
- queryKey: ["accounts", "favourites", username]
1326
+ const response = await CONFIG.hiveClient.call("bridge", "get_post", {
1327
+ author,
1328
+ permlink: cleanPermlink,
1329
+ observer
912
1330
  });
1331
+ if (!response) {
1332
+ return null;
1333
+ }
1334
+ const entry = num !== void 0 ? { ...response, num } : response;
1335
+ return filterDmcaEntry(entry);
913
1336
  },
914
- onError
1337
+ enabled: !!author && !!permlink && permlink.trim() !== "" && permlink.trim() !== "undefined"
915
1338
  });
916
1339
  }
917
- function useAccountFavouriteDelete(username, onSuccess, onError) {
918
- return useMutation({
919
- mutationKey: ["accounts", "favourites", "add", username],
920
- mutationFn: async (account) => {
921
- if (!username) {
922
- throw new Error("[SDK][Account][Bookmarks] \u2013 no active user");
1340
+ var SortOrder = /* @__PURE__ */ ((SortOrder2) => {
1341
+ SortOrder2["trending"] = "trending";
1342
+ SortOrder2["author_reputation"] = "author_reputation";
1343
+ SortOrder2["votes"] = "votes";
1344
+ SortOrder2["created"] = "created";
1345
+ return SortOrder2;
1346
+ })(SortOrder || {});
1347
+ function parseAsset2(value) {
1348
+ const match = value.match(/^(\d+\.?\d*)\s*([A-Z]+)$/);
1349
+ if (!match) return { amount: 0, symbol: "" };
1350
+ return {
1351
+ amount: parseFloat(match[1]),
1352
+ symbol: match[2]
1353
+ };
1354
+ }
1355
+ function sortDiscussions(entry, discussion, order) {
1356
+ const allPayout = (c) => parseAsset2(c.pending_payout_value).amount + parseAsset2(c.author_payout_value).amount + parseAsset2(c.curator_payout_value).amount;
1357
+ const absNegative = (a) => a.net_rshares < 0;
1358
+ const isPinned = (a) => entry.json_metadata?.pinned_reply === `${a.author}/${a.permlink}`;
1359
+ const sortOrders = {
1360
+ trending: (a, b) => {
1361
+ if (absNegative(a)) {
1362
+ return 1;
923
1363
  }
924
- const fetchApi = getBoundFetch();
925
- const response = await fetchApi(
926
- CONFIG.privateApiHost + "/private-api/favorites-delete",
927
- {
928
- method: "POST",
929
- headers: {
930
- "Content-Type": "application/json"
931
- },
932
- body: JSON.stringify({
933
- account,
934
- code: getAccessToken(username)
935
- })
936
- }
937
- );
938
- return response.json();
1364
+ if (absNegative(b)) {
1365
+ return -1;
1366
+ }
1367
+ const _a = allPayout(a);
1368
+ const _b = allPayout(b);
1369
+ if (_a !== _b) {
1370
+ return _b - _a;
1371
+ }
1372
+ return 0;
939
1373
  },
940
- onSuccess: () => {
941
- onSuccess();
942
- getQueryClient().invalidateQueries({
943
- queryKey: ["accounts", "favourites", username]
944
- });
1374
+ author_reputation: (a, b) => {
1375
+ const keyA = a.author_reputation;
1376
+ const keyB = b.author_reputation;
1377
+ if (keyA > keyB) return -1;
1378
+ if (keyA < keyB) return 1;
1379
+ return 0;
945
1380
  },
946
- onError
947
- });
1381
+ votes: (a, b) => {
1382
+ const keyA = a.children;
1383
+ const keyB = b.children;
1384
+ if (keyA > keyB) return -1;
1385
+ if (keyA < keyB) return 1;
1386
+ return 0;
1387
+ },
1388
+ created: (a, b) => {
1389
+ if (absNegative(a)) {
1390
+ return 1;
1391
+ }
1392
+ if (absNegative(b)) {
1393
+ return -1;
1394
+ }
1395
+ const keyA = Date.parse(a.created);
1396
+ const keyB = Date.parse(b.created);
1397
+ if (keyA > keyB) return -1;
1398
+ if (keyA < keyB) return 1;
1399
+ return 0;
1400
+ }
1401
+ };
1402
+ const sorted = discussion.sort(sortOrders[order]);
1403
+ const pinnedIndex = sorted.findIndex((i) => isPinned(i));
1404
+ const pinned = sorted[pinnedIndex];
1405
+ if (pinnedIndex >= 0) {
1406
+ sorted.splice(pinnedIndex, 1);
1407
+ sorted.unshift(pinned);
1408
+ }
1409
+ return sorted;
948
1410
  }
949
- function dedupeAndSortKeyAuths(existing, additions) {
950
- const merged = /* @__PURE__ */ new Map();
951
- existing.forEach(([key, weight]) => {
952
- merged.set(key.toString(), weight);
953
- });
954
- additions.forEach(([key, weight]) => {
955
- merged.set(key.toString(), weight);
1411
+ function getDiscussionsQueryOptions(entry, order = "created" /* created */, enabled = true, observer) {
1412
+ return queryOptions({
1413
+ queryKey: [
1414
+ "posts",
1415
+ "discussions",
1416
+ entry?.author,
1417
+ entry?.permlink,
1418
+ order,
1419
+ observer || entry?.author
1420
+ ],
1421
+ queryFn: async () => {
1422
+ if (!entry) {
1423
+ return [];
1424
+ }
1425
+ const response = await CONFIG.hiveClient.call("bridge", "get_discussion", {
1426
+ author: entry.author,
1427
+ permlink: entry.permlink,
1428
+ observer: observer || entry.author
1429
+ });
1430
+ const results = response ? Array.from(Object.values(response)) : [];
1431
+ return filterDmcaEntry(results);
1432
+ },
1433
+ enabled: enabled && !!entry,
1434
+ select: (data) => sortDiscussions(entry, data, order)
956
1435
  });
957
- return Array.from(merged.entries()).sort(([keyA], [keyB]) => keyA.localeCompare(keyB)).map(([key, weight]) => [key, weight]);
958
1436
  }
959
- function useAccountUpdateKeyAuths(username, options) {
960
- const { data: accountData } = useQuery(getAccountFullQueryOptions(username));
961
- return useMutation({
962
- mutationKey: ["accounts", "keys-update", username],
963
- mutationFn: async ({ keys, keepCurrent = false, currentKey }) => {
964
- if (!accountData) {
965
- throw new Error(
966
- "[SDK][Update password] \u2013 cannot update keys for anon user"
1437
+ function getAccountPostsInfiniteQueryOptions(username, filter = "posts", limit = 20, observer = "", enabled = true) {
1438
+ return infiniteQueryOptions({
1439
+ queryKey: ["posts", "account-posts", username ?? "", filter, limit, observer],
1440
+ enabled: !!username && enabled,
1441
+ initialPageParam: {
1442
+ author: void 0,
1443
+ permlink: void 0,
1444
+ hasNextPage: true
1445
+ },
1446
+ queryFn: async ({ pageParam }) => {
1447
+ if (!pageParam?.hasNextPage || !username) return [];
1448
+ const rpcParams = {
1449
+ sort: filter,
1450
+ account: username,
1451
+ limit,
1452
+ ...observer && observer.length > 0 ? { observer } : {},
1453
+ ...pageParam.author ? { start_author: pageParam.author } : {},
1454
+ ...pageParam.permlink ? { start_permlink: pageParam.permlink } : {}
1455
+ };
1456
+ try {
1457
+ if (CONFIG.dmcaAccounts.includes(username)) return [];
1458
+ const resp = await CONFIG.hiveClient.call(
1459
+ "bridge",
1460
+ "get_account_posts",
1461
+ rpcParams
967
1462
  );
1463
+ if (resp && Array.isArray(resp)) {
1464
+ return filterDmcaEntry(resp);
1465
+ }
1466
+ return [];
1467
+ } catch (err) {
1468
+ console.error("[SDK] get_account_posts error:", err);
1469
+ return [];
968
1470
  }
969
- const prepareAuth = (keyName) => {
970
- const auth = R4.clone(accountData[keyName]);
971
- auth.key_auths = dedupeAndSortKeyAuths(
972
- keepCurrent ? auth.key_auths : [],
973
- keys.map(
974
- (values, i) => [values[keyName].createPublic().toString(), i + 1]
975
- )
976
- );
977
- return auth;
978
- };
979
- return CONFIG.hiveClient.broadcast.updateAccount(
980
- {
981
- account: username,
982
- json_metadata: accountData.json_metadata,
983
- owner: prepareAuth("owner"),
984
- active: prepareAuth("active"),
985
- posting: prepareAuth("posting"),
986
- memo_key: keepCurrent ? accountData.memo_key : keys[0].memo_key.createPublic().toString()
987
- },
988
- currentKey
989
- );
990
1471
  },
991
- ...options
1472
+ getNextPageParam: (lastPage) => {
1473
+ const last = lastPage?.[lastPage.length - 1];
1474
+ const hasNextPage = (lastPage?.length ?? 0) === limit;
1475
+ if (!hasNextPage) {
1476
+ return void 0;
1477
+ }
1478
+ return {
1479
+ author: last?.author,
1480
+ permlink: last?.permlink,
1481
+ hasNextPage
1482
+ };
1483
+ }
992
1484
  });
993
1485
  }
994
- function useAccountUpdatePassword(username, options) {
995
- const { data: accountData } = useQuery(getAccountFullQueryOptions(username));
996
- const { mutateAsync: updateKeys } = useAccountUpdateKeyAuths(username);
997
- return useMutation({
1486
+ function getPostsRankedInfiniteQueryOptions(sort, tag, limit = 20, observer = "", enabled = true, _options = {}) {
1487
+ return infiniteQueryOptions({
1488
+ queryKey: ["posts", "posts-ranked", sort, tag, limit, observer],
1489
+ queryFn: async ({ pageParam }) => {
1490
+ if (!pageParam.hasNextPage) {
1491
+ return [];
1492
+ }
1493
+ let sanitizedTag = tag;
1494
+ if (CONFIG.dmcaTagRegexes.some((regex) => regex.test(tag))) {
1495
+ sanitizedTag = "";
1496
+ }
1497
+ const response = await CONFIG.hiveClient.call("bridge", "get_ranked_posts", {
1498
+ sort,
1499
+ start_author: pageParam.author,
1500
+ start_permlink: pageParam.permlink,
1501
+ limit,
1502
+ tag: sanitizedTag,
1503
+ observer
1504
+ });
1505
+ if (response && Array.isArray(response)) {
1506
+ const data = response;
1507
+ const sorted = sort === "hot" ? data : data.sort(
1508
+ (a, b) => new Date(b.created).getTime() - new Date(a.created).getTime()
1509
+ );
1510
+ const pinnedEntry = sorted.find((s) => s.stats?.is_pinned);
1511
+ const nonPinnedEntries = sorted.filter((s) => !s.stats?.is_pinned);
1512
+ const combined = [pinnedEntry, ...nonPinnedEntries].filter((s) => !!s);
1513
+ return filterDmcaEntry(combined);
1514
+ }
1515
+ return [];
1516
+ },
1517
+ enabled,
1518
+ initialPageParam: {
1519
+ author: void 0,
1520
+ permlink: void 0,
1521
+ hasNextPage: true
1522
+ },
1523
+ getNextPageParam: (lastPage) => {
1524
+ const last = lastPage?.[lastPage.length - 1];
1525
+ return {
1526
+ author: last?.author,
1527
+ permlink: last?.permlink,
1528
+ hasNextPage: (lastPage?.length ?? 0) > 0
1529
+ };
1530
+ }
1531
+ });
1532
+ }
1533
+ function getReblogsQueryOptions(username, activeUsername, limit = 200) {
1534
+ return queryOptions({
1535
+ queryKey: ["posts", "reblogs", username ?? "", limit],
1536
+ queryFn: async () => {
1537
+ const response = await CONFIG.hiveClient.call("condenser_api", "get_blog_entries", [
1538
+ username ?? activeUsername,
1539
+ 0,
1540
+ limit
1541
+ ]);
1542
+ return response.filter(
1543
+ (i) => i.author !== activeUsername && !i.reblogged_on.startsWith("1970-")
1544
+ ).map((i) => ({ author: i.author, permlink: i.permlink }));
1545
+ },
1546
+ enabled: !!username
1547
+ });
1548
+ }
1549
+ function getSchedulesQueryOptions(activeUsername) {
1550
+ return queryOptions({
1551
+ queryKey: ["posts", "schedules", activeUsername],
1552
+ queryFn: async () => {
1553
+ if (!activeUsername) {
1554
+ return [];
1555
+ }
1556
+ const response = await fetch(CONFIG.privateApiHost + "/private-api/schedules", {
1557
+ method: "POST",
1558
+ headers: {
1559
+ "Content-Type": "application/json"
1560
+ },
1561
+ body: JSON.stringify({
1562
+ code: getAccessToken(activeUsername)
1563
+ })
1564
+ });
1565
+ if (!response.ok) {
1566
+ throw new Error(`Failed to fetch schedules: ${response.status}`);
1567
+ }
1568
+ return response.json();
1569
+ },
1570
+ enabled: !!activeUsername
1571
+ });
1572
+ }
1573
+ function getDraftsQueryOptions(activeUsername) {
1574
+ return queryOptions({
1575
+ queryKey: ["posts", "drafts", activeUsername],
1576
+ queryFn: async () => {
1577
+ if (!activeUsername) {
1578
+ return [];
1579
+ }
1580
+ const response = await fetch(CONFIG.privateApiHost + "/private-api/drafts", {
1581
+ method: "POST",
1582
+ headers: {
1583
+ "Content-Type": "application/json"
1584
+ },
1585
+ body: JSON.stringify({
1586
+ code: getAccessToken(activeUsername)
1587
+ })
1588
+ });
1589
+ if (!response.ok) {
1590
+ throw new Error(`Failed to fetch drafts: ${response.status}`);
1591
+ }
1592
+ return response.json();
1593
+ },
1594
+ enabled: !!activeUsername
1595
+ });
1596
+ }
1597
+ async function fetchUserImages(username) {
1598
+ const response = await fetch(CONFIG.privateApiHost + "/private-api/images", {
1599
+ method: "POST",
1600
+ headers: {
1601
+ "Content-Type": "application/json"
1602
+ },
1603
+ body: JSON.stringify({
1604
+ code: getAccessToken(username)
1605
+ })
1606
+ });
1607
+ if (!response.ok) {
1608
+ throw new Error(`Failed to fetch images: ${response.status}`);
1609
+ }
1610
+ return response.json();
1611
+ }
1612
+ function getImagesQueryOptions(username) {
1613
+ return queryOptions({
1614
+ queryKey: ["posts", "images", username],
1615
+ queryFn: async () => {
1616
+ if (!username) {
1617
+ return [];
1618
+ }
1619
+ return fetchUserImages(username);
1620
+ },
1621
+ enabled: !!username
1622
+ });
1623
+ }
1624
+ function getGalleryImagesQueryOptions(activeUsername) {
1625
+ return queryOptions({
1626
+ queryKey: ["posts", "gallery-images", activeUsername],
1627
+ queryFn: async () => {
1628
+ if (!activeUsername) {
1629
+ return [];
1630
+ }
1631
+ return fetchUserImages(activeUsername);
1632
+ },
1633
+ enabled: !!activeUsername
1634
+ });
1635
+ }
1636
+ function getCommentHistoryQueryOptions(author, permlink, onlyMeta = false) {
1637
+ return queryOptions({
1638
+ queryKey: ["posts", "comment-history", author, permlink, onlyMeta],
1639
+ queryFn: async ({ signal }) => {
1640
+ const response = await fetch(CONFIG.privateApiHost + "/private-api/comment-history", {
1641
+ method: "POST",
1642
+ headers: {
1643
+ "Content-Type": "application/json"
1644
+ },
1645
+ body: JSON.stringify({
1646
+ author,
1647
+ permlink,
1648
+ onlyMeta: onlyMeta ? "1" : ""
1649
+ }),
1650
+ signal
1651
+ });
1652
+ if (!response.ok) {
1653
+ throw new Error(`Failed to fetch comment history: ${response.status}`);
1654
+ }
1655
+ return response.json();
1656
+ },
1657
+ enabled: !!author && !!permlink
1658
+ });
1659
+ }
1660
+ function makeEntryPath2(author, permlink) {
1661
+ const cleanAuthor = author?.trim();
1662
+ const cleanPermlink = permlink?.trim();
1663
+ if (!cleanAuthor || !cleanPermlink) {
1664
+ throw new Error("Invalid entry path: author and permlink are required");
1665
+ }
1666
+ const normalizedAuthor = cleanAuthor.replace(/^@+/, "");
1667
+ const normalizedPermlink = cleanPermlink.replace(/^\/+/, "");
1668
+ if (!normalizedAuthor || !normalizedPermlink) {
1669
+ throw new Error("Invalid entry path: author and permlink cannot be empty after normalization");
1670
+ }
1671
+ return `@${normalizedAuthor}/${normalizedPermlink}`;
1672
+ }
1673
+ function getDeletedEntryQueryOptions(author, permlink) {
1674
+ const cleanPermlink = permlink?.trim();
1675
+ const cleanAuthor = author?.trim();
1676
+ const isValid = !!cleanAuthor && !!cleanPermlink && cleanPermlink !== "undefined";
1677
+ const entryPath = isValid ? makeEntryPath2(cleanAuthor, cleanPermlink) : "";
1678
+ return queryOptions({
1679
+ queryKey: ["posts", "deleted-entry", entryPath],
1680
+ queryFn: async ({ signal }) => {
1681
+ const response = await fetch(CONFIG.privateApiHost + "/private-api/comment-history", {
1682
+ method: "POST",
1683
+ headers: {
1684
+ "Content-Type": "application/json"
1685
+ },
1686
+ body: JSON.stringify({
1687
+ author,
1688
+ permlink: cleanPermlink || ""
1689
+ }),
1690
+ signal
1691
+ });
1692
+ if (!response.ok) {
1693
+ throw new Error(`Failed to fetch comment history: ${response.status}`);
1694
+ }
1695
+ return response.json();
1696
+ },
1697
+ select: (history) => {
1698
+ if (!history?.list?.[0]) {
1699
+ return null;
1700
+ }
1701
+ const { body, title, tags } = history.list[0];
1702
+ return {
1703
+ body,
1704
+ title,
1705
+ tags
1706
+ };
1707
+ },
1708
+ enabled: isValid
1709
+ });
1710
+ }
1711
+ function getPostTipsQueryOptions(author, permlink, isEnabled = true) {
1712
+ return queryOptions({
1713
+ queryKey: ["posts", "tips", author, permlink],
1714
+ queryFn: async () => {
1715
+ const response = await fetch(CONFIG.privateApiHost + "/private-api/post-tips", {
1716
+ method: "POST",
1717
+ headers: {
1718
+ "Content-Type": "application/json"
1719
+ },
1720
+ body: JSON.stringify({
1721
+ author,
1722
+ permlink
1723
+ })
1724
+ });
1725
+ if (!response.ok) {
1726
+ throw new Error(`Failed to fetch post tips: ${response.status}`);
1727
+ }
1728
+ return response.json();
1729
+ },
1730
+ enabled: !!author && !!permlink && isEnabled
1731
+ });
1732
+ }
1733
+
1734
+ // src/modules/posts/utils/waves-helpers.ts
1735
+ function normalizeContainer(entry, host) {
1736
+ return {
1737
+ ...entry,
1738
+ id: entry.id ?? entry.post_id,
1739
+ host
1740
+ };
1741
+ }
1742
+ function normalizeParent(entry) {
1743
+ return {
1744
+ ...entry,
1745
+ id: entry.id ?? entry.post_id
1746
+ };
1747
+ }
1748
+ function normalizeWaveEntryFromApi(entry, host) {
1749
+ if (!entry) {
1750
+ return null;
1751
+ }
1752
+ const containerSource = entry.container ?? entry;
1753
+ const container = normalizeContainer(containerSource, host);
1754
+ const parent = entry.parent ? normalizeParent(entry.parent) : void 0;
1755
+ return {
1756
+ ...entry,
1757
+ id: entry.id ?? entry.post_id,
1758
+ host,
1759
+ container,
1760
+ parent
1761
+ };
1762
+ }
1763
+ function toEntryArray(x) {
1764
+ return Array.isArray(x) ? x : [];
1765
+ }
1766
+ async function getVisibleFirstLevelThreadItems(container) {
1767
+ const queryOptions76 = getDiscussionsQueryOptions(container, "created" /* created */, true);
1768
+ const discussionItemsRaw = await CONFIG.queryClient.fetchQuery(queryOptions76);
1769
+ const discussionItems = toEntryArray(discussionItemsRaw);
1770
+ if (discussionItems.length <= 1) {
1771
+ return [];
1772
+ }
1773
+ const firstLevelItems = discussionItems.filter(
1774
+ ({ parent_author, parent_permlink }) => parent_author === container.author && parent_permlink === container.permlink
1775
+ );
1776
+ if (firstLevelItems.length === 0) {
1777
+ return [];
1778
+ }
1779
+ const visibleItems = firstLevelItems.filter((item) => !item.stats?.gray);
1780
+ return visibleItems;
1781
+ }
1782
+ function mapThreadItemsToWaveEntries(items, container, host) {
1783
+ if (items.length === 0) {
1784
+ return [];
1785
+ }
1786
+ return items.map((item) => {
1787
+ const parent = items.find(
1788
+ (i) => i.author === item.parent_author && i.permlink === item.parent_permlink && i.author !== host
1789
+ );
1790
+ return {
1791
+ ...item,
1792
+ id: item.post_id,
1793
+ host,
1794
+ container,
1795
+ parent
1796
+ };
1797
+ }).filter((entry) => entry.container.post_id !== entry.post_id).sort(
1798
+ (a, b) => new Date(b.created).getTime() - new Date(a.created).getTime()
1799
+ );
1800
+ }
1801
+
1802
+ // src/modules/posts/queries/get-waves-by-host-query-options.ts
1803
+ var THREAD_CONTAINER_BATCH_SIZE = 5;
1804
+ var MAX_CONTAINERS_TO_SCAN = 50;
1805
+ async function getThreads(host, pageParam) {
1806
+ let startAuthor = pageParam?.author;
1807
+ let startPermlink = pageParam?.permlink;
1808
+ let scannedContainers = 0;
1809
+ let skipContainerId = pageParam?.post_id;
1810
+ while (scannedContainers < MAX_CONTAINERS_TO_SCAN) {
1811
+ const rpcParams = {
1812
+ sort: "posts",
1813
+ // ProfileFilter.posts
1814
+ account: host,
1815
+ limit: THREAD_CONTAINER_BATCH_SIZE,
1816
+ ...startAuthor ? { start_author: startAuthor } : {},
1817
+ ...startPermlink ? { start_permlink: startPermlink } : {}
1818
+ };
1819
+ const containers = await CONFIG.hiveClient.call(
1820
+ "bridge",
1821
+ "get_account_posts",
1822
+ rpcParams
1823
+ );
1824
+ if (!containers || containers.length === 0) {
1825
+ return null;
1826
+ }
1827
+ const normalizedContainers = containers.map((container) => {
1828
+ container.id = container.post_id;
1829
+ container.host = host;
1830
+ return container;
1831
+ });
1832
+ for (const container of normalizedContainers) {
1833
+ if (skipContainerId && container.post_id === skipContainerId) {
1834
+ skipContainerId = void 0;
1835
+ continue;
1836
+ }
1837
+ scannedContainers += 1;
1838
+ if (container.stats?.gray) {
1839
+ startAuthor = container.author;
1840
+ startPermlink = container.permlink;
1841
+ continue;
1842
+ }
1843
+ const visibleItems = await getVisibleFirstLevelThreadItems(container);
1844
+ if (visibleItems.length === 0) {
1845
+ startAuthor = container.author;
1846
+ startPermlink = container.permlink;
1847
+ continue;
1848
+ }
1849
+ return {
1850
+ entries: mapThreadItemsToWaveEntries(visibleItems, container, host)
1851
+ };
1852
+ }
1853
+ const lastContainer = normalizedContainers[normalizedContainers.length - 1];
1854
+ if (!lastContainer) {
1855
+ return null;
1856
+ }
1857
+ startAuthor = lastContainer.author;
1858
+ startPermlink = lastContainer.permlink;
1859
+ }
1860
+ return null;
1861
+ }
1862
+ function getWavesByHostQueryOptions(host) {
1863
+ return infiniteQueryOptions({
1864
+ queryKey: ["posts", "waves", "by-host", host],
1865
+ initialPageParam: void 0,
1866
+ queryFn: async ({ pageParam }) => {
1867
+ const result = await getThreads(host, pageParam);
1868
+ if (!result) return [];
1869
+ return result.entries;
1870
+ },
1871
+ getNextPageParam: (lastPage) => lastPage?.[0]?.container
1872
+ });
1873
+ }
1874
+ var DEFAULT_TAG_FEED_LIMIT = 40;
1875
+ function getWavesByTagQueryOptions(host, tag, limit = DEFAULT_TAG_FEED_LIMIT) {
1876
+ return infiniteQueryOptions({
1877
+ queryKey: ["posts", "waves", "by-tag", host, tag],
1878
+ initialPageParam: void 0,
1879
+ queryFn: async ({ signal }) => {
1880
+ try {
1881
+ const url = new URL(CONFIG.privateApiHost + "/private-api/waves/tags");
1882
+ url.searchParams.set("container", host);
1883
+ url.searchParams.set("tag", tag);
1884
+ const response = await fetch(url.toString(), {
1885
+ method: "GET",
1886
+ headers: {
1887
+ "Content-Type": "application/json"
1888
+ },
1889
+ signal
1890
+ });
1891
+ if (!response.ok) {
1892
+ throw new Error(`Failed to fetch waves by tag: ${response.status}`);
1893
+ }
1894
+ const data = await response.json();
1895
+ const result = data.slice(0, limit).map((entry) => normalizeWaveEntryFromApi(entry, host)).filter((entry) => Boolean(entry));
1896
+ return result.sort(
1897
+ (a, b) => new Date(b.created).getTime() - new Date(a.created).getTime()
1898
+ );
1899
+ } catch (error) {
1900
+ console.error("[SDK] Failed to fetch waves by tag", error);
1901
+ return [];
1902
+ }
1903
+ },
1904
+ getNextPageParam: () => void 0
1905
+ });
1906
+ }
1907
+ function getWavesFollowingQueryOptions(host, username) {
1908
+ const normalizedUsername = username?.trim().toLowerCase();
1909
+ return infiniteQueryOptions({
1910
+ queryKey: ["posts", "waves", "following", host, normalizedUsername ?? ""],
1911
+ enabled: Boolean(normalizedUsername),
1912
+ initialPageParam: void 0,
1913
+ queryFn: async ({ signal }) => {
1914
+ if (!normalizedUsername) {
1915
+ return [];
1916
+ }
1917
+ try {
1918
+ const url = new URL(CONFIG.privateApiHost + "/private-api/waves/following");
1919
+ url.searchParams.set("container", host);
1920
+ url.searchParams.set("username", normalizedUsername);
1921
+ const response = await fetch(url.toString(), {
1922
+ method: "GET",
1923
+ headers: {
1924
+ "Content-Type": "application/json"
1925
+ },
1926
+ signal
1927
+ });
1928
+ if (!response.ok) {
1929
+ throw new Error(`Failed to fetch waves following feed: ${response.status}`);
1930
+ }
1931
+ const data = await response.json();
1932
+ if (!Array.isArray(data) || data.length === 0) {
1933
+ return [];
1934
+ }
1935
+ const flattened = data.map((entry) => normalizeWaveEntryFromApi(entry, host)).filter((entry) => Boolean(entry));
1936
+ if (flattened.length === 0) {
1937
+ return [];
1938
+ }
1939
+ return flattened.sort(
1940
+ (a, b) => new Date(b.created).getTime() - new Date(a.created).getTime()
1941
+ );
1942
+ } catch (error) {
1943
+ console.error("[SDK] Failed to fetch waves following feed", error);
1944
+ return [];
1945
+ }
1946
+ },
1947
+ getNextPageParam: () => void 0
1948
+ });
1949
+ }
1950
+ function getWavesTrendingTagsQueryOptions(host, hours = 24) {
1951
+ return queryOptions({
1952
+ queryKey: ["posts", "waves", "trending-tags", host, hours],
1953
+ queryFn: async ({ signal }) => {
1954
+ try {
1955
+ const url = new URL(CONFIG.privateApiHost + "/private-api/waves/trending/tags");
1956
+ url.searchParams.set("container", host);
1957
+ url.searchParams.set("hours", hours.toString());
1958
+ const response = await fetch(url.toString(), {
1959
+ method: "GET",
1960
+ headers: {
1961
+ "Content-Type": "application/json"
1962
+ },
1963
+ signal
1964
+ });
1965
+ if (!response.ok) {
1966
+ throw new Error(`Failed to fetch waves trending tags: ${response.status}`);
1967
+ }
1968
+ const data = await response.json();
1969
+ return data.map(({ tag, posts }) => ({ tag, posts }));
1970
+ } catch (error) {
1971
+ console.error("[SDK] Failed to fetch waves trending tags", error);
1972
+ return [];
1973
+ }
1974
+ }
1975
+ });
1976
+ }
1977
+
1978
+ // src/modules/accounts/queries/get-account-vote-history-infinite-query-options.ts
1979
+ function isEntry(x) {
1980
+ return !!x && typeof x === "object" && "author" in x && "permlink" in x && "active_votes" in x;
1981
+ }
1982
+ function getDays(createdDate) {
1983
+ const past = new Date(createdDate);
1984
+ const now = /* @__PURE__ */ new Date();
1985
+ const diffMs = now.getTime() - past.getTime();
1986
+ return diffMs / (1e3 * 60 * 60 * 24);
1987
+ }
1988
+ function getAccountVoteHistoryInfiniteQueryOptions(username, options) {
1989
+ const { limit = 20, filters = [], dayLimit = 7 } = options ?? {};
1990
+ return infiniteQueryOptions({
1991
+ queryKey: ["accounts", "vote-history", username, limit],
1992
+ initialPageParam: { start: -1 },
1993
+ queryFn: async ({ pageParam }) => {
1994
+ const { start } = pageParam;
1995
+ const response = await CONFIG.hiveClient.call(
1996
+ "condenser_api",
1997
+ "get_account_history",
1998
+ [username, start, limit, ...filters]
1999
+ );
2000
+ const mappedResults = response.map(([num, historyObj]) => ({
2001
+ ...historyObj.op[1],
2002
+ num,
2003
+ timestamp: historyObj.timestamp
2004
+ }));
2005
+ const result = mappedResults.filter(
2006
+ (filtered) => filtered.voter === username && filtered.weight !== 0 && getDays(filtered.timestamp) <= dayLimit
2007
+ );
2008
+ const entries = [];
2009
+ for (const obj of result) {
2010
+ const post = await CONFIG.queryClient.fetchQuery(
2011
+ getPostQueryOptions(obj.author, obj.permlink)
2012
+ );
2013
+ if (isEntry(post)) entries.push(post);
2014
+ }
2015
+ const [firstHistory] = response;
2016
+ return {
2017
+ lastDate: firstHistory ? getDays(firstHistory[1].timestamp) : 0,
2018
+ lastItemFetched: firstHistory ? firstHistory[0] : start,
2019
+ entries
2020
+ };
2021
+ },
2022
+ getNextPageParam: (lastPage) => ({
2023
+ start: lastPage.lastItemFetched
2024
+ })
2025
+ });
2026
+ }
2027
+
2028
+ // src/modules/accounts/mutations/use-account-update.ts
2029
+ function useAccountUpdate(username) {
2030
+ const queryClient = useQueryClient();
2031
+ const { data } = useQuery(getAccountFullQueryOptions(username));
2032
+ return useBroadcastMutation(
2033
+ ["accounts", "update"],
2034
+ username,
2035
+ (payload) => {
2036
+ if (!data) {
2037
+ throw new Error("[SDK][Accounts] \u2013 cannot update not existing account");
2038
+ }
2039
+ const profile = buildProfileMetadata({
2040
+ existingProfile: extractAccountProfile(data),
2041
+ profile: payload.profile,
2042
+ tokens: payload.tokens
2043
+ });
2044
+ return [
2045
+ [
2046
+ "account_update2",
2047
+ {
2048
+ account: username,
2049
+ json_metadata: "",
2050
+ extensions: [],
2051
+ posting_json_metadata: JSON.stringify({
2052
+ profile
2053
+ })
2054
+ }
2055
+ ]
2056
+ ];
2057
+ },
2058
+ (_, variables) => queryClient.setQueryData(
2059
+ getAccountFullQueryOptions(username).queryKey,
2060
+ (data2) => {
2061
+ if (!data2) {
2062
+ return data2;
2063
+ }
2064
+ const obj = R4.clone(data2);
2065
+ obj.profile = buildProfileMetadata({
2066
+ existingProfile: extractAccountProfile(data2),
2067
+ profile: variables.profile,
2068
+ tokens: variables.tokens
2069
+ });
2070
+ return obj;
2071
+ }
2072
+ )
2073
+ );
2074
+ }
2075
+ function useAccountRelationsUpdate(reference, target, onSuccess, onError) {
2076
+ return useMutation({
2077
+ mutationKey: ["accounts", "relation", "update", reference, target],
2078
+ mutationFn: async (kind) => {
2079
+ const relationsQuery = getRelationshipBetweenAccountsQueryOptions(
2080
+ reference,
2081
+ target
2082
+ );
2083
+ await getQueryClient().prefetchQuery(relationsQuery);
2084
+ const actualRelation = getQueryClient().getQueryData(
2085
+ relationsQuery.queryKey
2086
+ );
2087
+ await broadcastJson(reference, "follow", [
2088
+ "follow",
2089
+ {
2090
+ follower: reference,
2091
+ following: target,
2092
+ what: [
2093
+ ...kind === "toggle-ignore" && !actualRelation?.ignores ? ["ignore"] : [],
2094
+ ...kind === "toggle-follow" && !actualRelation?.follows ? ["blog"] : []
2095
+ ]
2096
+ }
2097
+ ]);
2098
+ return {
2099
+ ...actualRelation,
2100
+ ignores: kind === "toggle-ignore" ? !actualRelation?.ignores : actualRelation?.ignores,
2101
+ follows: kind === "toggle-follow" ? !actualRelation?.follows : actualRelation?.follows
2102
+ };
2103
+ },
2104
+ onError,
2105
+ onSuccess(data) {
2106
+ onSuccess(data);
2107
+ getQueryClient().setQueryData(
2108
+ ["accounts", "relations", reference, target],
2109
+ data
2110
+ );
2111
+ }
2112
+ });
2113
+ }
2114
+ function useBookmarkAdd(username, onSuccess, onError) {
2115
+ return useMutation({
2116
+ mutationKey: ["accounts", "bookmarks", "add", username],
2117
+ mutationFn: async ({ author, permlink }) => {
2118
+ if (!username) {
2119
+ throw new Error("[SDK][Account][Bookmarks] \u2013 no active user");
2120
+ }
2121
+ const fetchApi = getBoundFetch();
2122
+ const response = await fetchApi(
2123
+ CONFIG.privateApiHost + "/private-api/bookmarks-add",
2124
+ {
2125
+ method: "POST",
2126
+ headers: {
2127
+ "Content-Type": "application/json"
2128
+ },
2129
+ body: JSON.stringify({
2130
+ author,
2131
+ permlink,
2132
+ code: getAccessToken(username)
2133
+ })
2134
+ }
2135
+ );
2136
+ return response.json();
2137
+ },
2138
+ onSuccess: () => {
2139
+ onSuccess();
2140
+ getQueryClient().invalidateQueries({
2141
+ queryKey: ["accounts", "bookmarks", username]
2142
+ });
2143
+ },
2144
+ onError
2145
+ });
2146
+ }
2147
+ function useBookmarkDelete(username, onSuccess, onError) {
2148
+ return useMutation({
2149
+ mutationKey: ["accounts", "bookmarks", "delete", username],
2150
+ mutationFn: async (bookmarkId) => {
2151
+ if (!username) {
2152
+ throw new Error("[SDK][Account][Bookmarks] \u2013 no active user");
2153
+ }
2154
+ const fetchApi = getBoundFetch();
2155
+ const response = await fetchApi(
2156
+ CONFIG.privateApiHost + "/private-api/bookmarks-delete",
2157
+ {
2158
+ method: "POST",
2159
+ headers: {
2160
+ "Content-Type": "application/json"
2161
+ },
2162
+ body: JSON.stringify({
2163
+ id: bookmarkId,
2164
+ code: getAccessToken(username)
2165
+ })
2166
+ }
2167
+ );
2168
+ return response.json();
2169
+ },
2170
+ onSuccess: () => {
2171
+ onSuccess();
2172
+ getQueryClient().invalidateQueries({
2173
+ queryKey: ["accounts", "bookmarks", username]
2174
+ });
2175
+ },
2176
+ onError
2177
+ });
2178
+ }
2179
+ function useAccountFavouriteAdd(username, onSuccess, onError) {
2180
+ return useMutation({
2181
+ mutationKey: ["accounts", "favourites", "add", username],
2182
+ mutationFn: async (account) => {
2183
+ if (!username) {
2184
+ throw new Error("[SDK][Account][Bookmarks] \u2013 no active user");
2185
+ }
2186
+ const fetchApi = getBoundFetch();
2187
+ const response = await fetchApi(
2188
+ CONFIG.privateApiHost + "/private-api/favorites-add",
2189
+ {
2190
+ method: "POST",
2191
+ headers: {
2192
+ "Content-Type": "application/json"
2193
+ },
2194
+ body: JSON.stringify({
2195
+ account,
2196
+ code: getAccessToken(username)
2197
+ })
2198
+ }
2199
+ );
2200
+ return response.json();
2201
+ },
2202
+ onSuccess: () => {
2203
+ onSuccess();
2204
+ getQueryClient().invalidateQueries({
2205
+ queryKey: ["accounts", "favourites", username]
2206
+ });
2207
+ },
2208
+ onError
2209
+ });
2210
+ }
2211
+ function useAccountFavouriteDelete(username, onSuccess, onError) {
2212
+ return useMutation({
2213
+ mutationKey: ["accounts", "favourites", "add", username],
2214
+ mutationFn: async (account) => {
2215
+ if (!username) {
2216
+ throw new Error("[SDK][Account][Bookmarks] \u2013 no active user");
2217
+ }
2218
+ const fetchApi = getBoundFetch();
2219
+ const response = await fetchApi(
2220
+ CONFIG.privateApiHost + "/private-api/favorites-delete",
2221
+ {
2222
+ method: "POST",
2223
+ headers: {
2224
+ "Content-Type": "application/json"
2225
+ },
2226
+ body: JSON.stringify({
2227
+ account,
2228
+ code: getAccessToken(username)
2229
+ })
2230
+ }
2231
+ );
2232
+ return response.json();
2233
+ },
2234
+ onSuccess: () => {
2235
+ onSuccess();
2236
+ getQueryClient().invalidateQueries({
2237
+ queryKey: ["accounts", "favourites", username]
2238
+ });
2239
+ },
2240
+ onError
2241
+ });
2242
+ }
2243
+ function dedupeAndSortKeyAuths(existing, additions) {
2244
+ const merged = /* @__PURE__ */ new Map();
2245
+ existing.forEach(([key, weight]) => {
2246
+ merged.set(key.toString(), weight);
2247
+ });
2248
+ additions.forEach(([key, weight]) => {
2249
+ merged.set(key.toString(), weight);
2250
+ });
2251
+ return Array.from(merged.entries()).sort(([keyA], [keyB]) => keyA.localeCompare(keyB)).map(([key, weight]) => [key, weight]);
2252
+ }
2253
+ function useAccountUpdateKeyAuths(username, options) {
2254
+ const { data: accountData } = useQuery(getAccountFullQueryOptions(username));
2255
+ return useMutation({
2256
+ mutationKey: ["accounts", "keys-update", username],
2257
+ mutationFn: async ({ keys, keepCurrent = false, currentKey }) => {
2258
+ if (!accountData) {
2259
+ throw new Error(
2260
+ "[SDK][Update password] \u2013 cannot update keys for anon user"
2261
+ );
2262
+ }
2263
+ const prepareAuth = (keyName) => {
2264
+ const auth = R4.clone(accountData[keyName]);
2265
+ auth.key_auths = dedupeAndSortKeyAuths(
2266
+ keepCurrent ? auth.key_auths : [],
2267
+ keys.map(
2268
+ (values, i) => [values[keyName].createPublic().toString(), i + 1]
2269
+ )
2270
+ );
2271
+ return auth;
2272
+ };
2273
+ return CONFIG.hiveClient.broadcast.updateAccount(
2274
+ {
2275
+ account: username,
2276
+ json_metadata: accountData.json_metadata,
2277
+ owner: prepareAuth("owner"),
2278
+ active: prepareAuth("active"),
2279
+ posting: prepareAuth("posting"),
2280
+ memo_key: keepCurrent ? accountData.memo_key : keys[0].memo_key.createPublic().toString()
2281
+ },
2282
+ currentKey
2283
+ );
2284
+ },
2285
+ ...options
2286
+ });
2287
+ }
2288
+ function useAccountUpdatePassword(username, options) {
2289
+ const { data: accountData } = useQuery(getAccountFullQueryOptions(username));
2290
+ const { mutateAsync: updateKeys } = useAccountUpdateKeyAuths(username);
2291
+ return useMutation({
998
2292
  mutationKey: ["accounts", "password-update", username],
999
2293
  mutationFn: async ({
1000
2294
  newPassword,
@@ -1003,745 +2297,1585 @@ function useAccountUpdatePassword(username, options) {
1003
2297
  }) => {
1004
2298
  if (!accountData) {
1005
2299
  throw new Error(
1006
- "[SDK][Update password] \u2013 cannot update password for anon user"
2300
+ "[SDK][Update password] \u2013 cannot update password for anon user"
2301
+ );
2302
+ }
2303
+ const currentKey = PrivateKey.fromLogin(
2304
+ username,
2305
+ currentPassword,
2306
+ "owner"
2307
+ );
2308
+ return updateKeys({
2309
+ currentKey,
2310
+ keepCurrent,
2311
+ keys: [
2312
+ {
2313
+ owner: PrivateKey.fromLogin(username, newPassword, "owner"),
2314
+ active: PrivateKey.fromLogin(username, newPassword, "active"),
2315
+ posting: PrivateKey.fromLogin(username, newPassword, "posting"),
2316
+ memo_key: PrivateKey.fromLogin(username, newPassword, "memo")
2317
+ }
2318
+ ]
2319
+ });
2320
+ },
2321
+ ...options
2322
+ });
2323
+ }
2324
+ function useAccountRevokePosting(username, options) {
2325
+ const queryClient = useQueryClient();
2326
+ const { data } = useQuery(getAccountFullQueryOptions(username));
2327
+ return useMutation({
2328
+ mutationKey: ["accounts", "revoke-posting", data?.name],
2329
+ mutationFn: async ({ accountName, type, key }) => {
2330
+ if (!data) {
2331
+ throw new Error(
2332
+ "[SDK][Accounts] \u2013\xA0cannot revoke posting for anonymous user"
2333
+ );
2334
+ }
2335
+ const posting = R4.pipe(
2336
+ {},
2337
+ R4.mergeDeep(data.posting)
2338
+ );
2339
+ posting.account_auths = posting.account_auths.filter(
2340
+ ([account]) => account !== accountName
2341
+ );
2342
+ const operationBody = {
2343
+ account: data.name,
2344
+ posting,
2345
+ memo_key: data.memo_key,
2346
+ json_metadata: data.json_metadata
2347
+ };
2348
+ if (type === "key" && key) {
2349
+ return CONFIG.hiveClient.broadcast.updateAccount(operationBody, key);
2350
+ } else if (type === "keychain") {
2351
+ return keychain_exports.broadcast(
2352
+ data.name,
2353
+ [["account_update", operationBody]],
2354
+ "Active"
2355
+ );
2356
+ } else {
2357
+ const params = {
2358
+ callback: `https://ecency.com/@${data.name}/permissions`
2359
+ };
2360
+ return hs.sendOperation(
2361
+ ["account_update", operationBody],
2362
+ params,
2363
+ () => {
2364
+ }
2365
+ );
2366
+ }
2367
+ },
2368
+ onError: options.onError,
2369
+ onSuccess: (resp, payload, ctx) => {
2370
+ options.onSuccess?.(resp, payload, ctx);
2371
+ queryClient.setQueryData(
2372
+ getAccountFullQueryOptions(username).queryKey,
2373
+ (data2) => ({
2374
+ ...data2,
2375
+ posting: {
2376
+ ...data2?.posting,
2377
+ account_auths: data2?.posting?.account_auths?.filter(
2378
+ ([account]) => account !== payload.accountName
2379
+ ) ?? []
2380
+ }
2381
+ })
2382
+ );
2383
+ }
2384
+ });
2385
+ }
2386
+ function useAccountUpdateRecovery(username, options) {
2387
+ const { data } = useQuery(getAccountFullQueryOptions(username));
2388
+ return useMutation({
2389
+ mutationKey: ["accounts", "recovery", data?.name],
2390
+ mutationFn: async ({ accountName, type, key, email }) => {
2391
+ if (!data) {
2392
+ throw new Error(
2393
+ "[SDK][Accounts] \u2013\xA0cannot change recovery for anonymous user"
2394
+ );
2395
+ }
2396
+ const operationBody = {
2397
+ account_to_recover: data.name,
2398
+ new_recovery_account: accountName,
2399
+ extensions: []
2400
+ };
2401
+ if (type === "ecency") {
2402
+ const fetchApi = getBoundFetch();
2403
+ return fetchApi(CONFIG.privateApiHost + "/private-api/recoveries-add", {
2404
+ method: "POST",
2405
+ body: JSON.stringify({
2406
+ code: getAccessToken(data.name),
2407
+ email,
2408
+ publicKeys: [
2409
+ ...data.owner.key_auths,
2410
+ ...data.active.key_auths,
2411
+ ...data.posting.key_auths,
2412
+ data.memo_key
2413
+ ]
2414
+ })
2415
+ });
2416
+ } else if (type === "key" && key) {
2417
+ return CONFIG.hiveClient.broadcast.sendOperations(
2418
+ [["change_recovery_account", operationBody]],
2419
+ key
2420
+ );
2421
+ } else if (type === "keychain") {
2422
+ return keychain_exports.broadcast(
2423
+ data.name,
2424
+ [["change_recovery_account", operationBody]],
2425
+ "Active"
2426
+ );
2427
+ } else {
2428
+ const params = {
2429
+ callback: `https://ecency.com/@${data.name}/permissions`
2430
+ };
2431
+ return hs.sendOperation(
2432
+ ["change_recovery_account", operationBody],
2433
+ params,
2434
+ () => {
2435
+ }
2436
+ );
2437
+ }
2438
+ },
2439
+ onError: options.onError,
2440
+ onSuccess: options.onSuccess
2441
+ });
2442
+ }
2443
+ function useAccountRevokeKey(username, options) {
2444
+ const { data: accountData } = useQuery(getAccountFullQueryOptions(username));
2445
+ return useMutation({
2446
+ mutationKey: ["accounts", "revoke-key", accountData?.name],
2447
+ mutationFn: async ({ currentKey, revokingKey }) => {
2448
+ if (!accountData) {
2449
+ throw new Error(
2450
+ "[SDK][Update password] \u2013 cannot update keys for anon user"
2451
+ );
2452
+ }
2453
+ const prepareAuth = (keyName) => {
2454
+ const auth = R4.clone(accountData[keyName]);
2455
+ auth.key_auths = auth.key_auths.filter(
2456
+ ([key]) => key !== revokingKey.toString()
2457
+ );
2458
+ return auth;
2459
+ };
2460
+ return CONFIG.hiveClient.broadcast.updateAccount(
2461
+ {
2462
+ account: accountData.name,
2463
+ json_metadata: accountData.json_metadata,
2464
+ owner: prepareAuth("owner"),
2465
+ active: prepareAuth("active"),
2466
+ posting: prepareAuth("posting"),
2467
+ memo_key: accountData.memo_key
2468
+ },
2469
+ currentKey
2470
+ );
2471
+ },
2472
+ ...options
2473
+ });
2474
+ }
2475
+ function useSignOperationByKey(username) {
2476
+ return useMutation({
2477
+ mutationKey: ["operations", "sign", username],
2478
+ mutationFn: ({
2479
+ operation,
2480
+ keyOrSeed
2481
+ }) => {
2482
+ if (!username) {
2483
+ throw new Error("[Operations][Sign] \u2013 cannot sign op with anon user");
2484
+ }
2485
+ let privateKey;
2486
+ if (keyOrSeed.split(" ").length === 12) {
2487
+ privateKey = PrivateKey.fromLogin(username, keyOrSeed, "active");
2488
+ } else if (cryptoUtils.isWif(keyOrSeed)) {
2489
+ privateKey = PrivateKey.fromString(keyOrSeed);
2490
+ } else {
2491
+ privateKey = PrivateKey.from(keyOrSeed);
2492
+ }
2493
+ return CONFIG.hiveClient.broadcast.sendOperations(
2494
+ [operation],
2495
+ privateKey
2496
+ );
2497
+ }
2498
+ });
2499
+ }
2500
+ function useSignOperationByKeychain(username, keyType = "Active") {
2501
+ return useMutation({
2502
+ mutationKey: ["operations", "sign-keychain", username],
2503
+ mutationFn: ({ operation }) => {
2504
+ if (!username) {
2505
+ throw new Error(
2506
+ "[SDK][Keychain] \u2013\xA0cannot sign operation with anon user"
1007
2507
  );
1008
2508
  }
1009
- const currentKey = PrivateKey.fromLogin(
1010
- username,
1011
- currentPassword,
1012
- "owner"
2509
+ return keychain_exports.broadcast(username, [operation], keyType);
2510
+ }
2511
+ });
2512
+ }
2513
+ function useSignOperationByHivesigner(callbackUri = "/") {
2514
+ return useMutation({
2515
+ mutationKey: ["operations", "sign-hivesigner", callbackUri],
2516
+ mutationFn: async ({ operation }) => {
2517
+ return hs.sendOperation(operation, { callback: callbackUri }, () => {
2518
+ });
2519
+ }
2520
+ });
2521
+ }
2522
+ function getChainPropertiesQueryOptions() {
2523
+ return queryOptions({
2524
+ queryKey: ["operations", "chain-properties"],
2525
+ queryFn: async () => {
2526
+ return await CONFIG.hiveClient.database.getChainProperties();
2527
+ }
2528
+ });
2529
+ }
2530
+ function useAddFragment(username) {
2531
+ return useMutation({
2532
+ mutationKey: ["posts", "add-fragment", username],
2533
+ mutationFn: async ({ title, body }) => {
2534
+ const fetchApi = getBoundFetch();
2535
+ const response = await fetchApi(
2536
+ CONFIG.privateApiHost + "/private-api/fragments-add",
2537
+ {
2538
+ method: "POST",
2539
+ body: JSON.stringify({
2540
+ code: getAccessToken(username),
2541
+ title,
2542
+ body
2543
+ }),
2544
+ headers: {
2545
+ "Content-Type": "application/json"
2546
+ }
2547
+ }
1013
2548
  );
1014
- return updateKeys({
1015
- currentKey,
1016
- keepCurrent,
1017
- keys: [
1018
- {
1019
- owner: PrivateKey.fromLogin(username, newPassword, "owner"),
1020
- active: PrivateKey.fromLogin(username, newPassword, "active"),
1021
- posting: PrivateKey.fromLogin(username, newPassword, "posting"),
1022
- memo_key: PrivateKey.fromLogin(username, newPassword, "memo")
2549
+ return response.json();
2550
+ },
2551
+ onSuccess(response) {
2552
+ getQueryClient().setQueryData(
2553
+ getFragmentsQueryOptions(username).queryKey,
2554
+ (data) => [response, ...data ?? []]
2555
+ );
2556
+ }
2557
+ });
2558
+ }
2559
+ function useEditFragment(username, fragmentId) {
2560
+ return useMutation({
2561
+ mutationKey: ["posts", "edit-fragment", username, fragmentId],
2562
+ mutationFn: async ({ title, body }) => {
2563
+ const fetchApi = getBoundFetch();
2564
+ const response = await fetchApi(
2565
+ CONFIG.privateApiHost + "/private-api/fragments-update",
2566
+ {
2567
+ method: "POST",
2568
+ body: JSON.stringify({
2569
+ code: getAccessToken(username),
2570
+ id: fragmentId,
2571
+ title,
2572
+ body
2573
+ }),
2574
+ headers: {
2575
+ "Content-Type": "application/json"
1023
2576
  }
1024
- ]
2577
+ }
2578
+ );
2579
+ return response.json();
2580
+ },
2581
+ onSuccess(response) {
2582
+ getQueryClient().setQueryData(
2583
+ getFragmentsQueryOptions(username).queryKey,
2584
+ (data) => {
2585
+ if (!data) {
2586
+ return [];
2587
+ }
2588
+ const index = data.findIndex(({ id }) => id === fragmentId);
2589
+ if (index >= 0) {
2590
+ data[index] = response;
2591
+ }
2592
+ return [...data];
2593
+ }
2594
+ );
2595
+ }
2596
+ });
2597
+ }
2598
+ function useRemoveFragment(username, fragmentId) {
2599
+ return useMutation({
2600
+ mutationKey: ["posts", "remove-fragment", username],
2601
+ mutationFn: async () => {
2602
+ const fetchApi = getBoundFetch();
2603
+ return fetchApi(CONFIG.privateApiHost + "/private-api/fragments-delete", {
2604
+ method: "POST",
2605
+ body: JSON.stringify({
2606
+ code: getAccessToken(username),
2607
+ id: fragmentId
2608
+ }),
2609
+ headers: {
2610
+ "Content-Type": "application/json"
2611
+ }
1025
2612
  });
1026
2613
  },
1027
- ...options
2614
+ onSuccess() {
2615
+ getQueryClient().setQueryData(
2616
+ getFragmentsQueryOptions(username).queryKey,
2617
+ (data) => [...data ?? []].filter(({ id }) => id !== fragmentId)
2618
+ );
2619
+ }
2620
+ });
2621
+ }
2622
+
2623
+ // src/modules/analytics/mutations/index.ts
2624
+ var mutations_exports = {};
2625
+ __export(mutations_exports, {
2626
+ useRecordActivity: () => useRecordActivity
2627
+ });
2628
+ function useRecordActivity(username, activityType) {
2629
+ return useMutation({
2630
+ mutationKey: ["analytics", activityType],
2631
+ mutationFn: async () => {
2632
+ if (!activityType) {
2633
+ throw new Error("[SDK][Analytics] \u2013 no activity type provided");
2634
+ }
2635
+ const fetchApi = getBoundFetch();
2636
+ await fetchApi(CONFIG.plausibleHost + "/api/event", {
2637
+ method: "POST",
2638
+ headers: {
2639
+ "Content-Type": "application/json"
2640
+ },
2641
+ body: JSON.stringify({
2642
+ name: activityType,
2643
+ url: window.location.href,
2644
+ domain: window.location.host,
2645
+ props: {
2646
+ username
2647
+ }
2648
+ })
2649
+ });
2650
+ }
2651
+ });
2652
+ }
2653
+ function getDiscoverLeaderboardQueryOptions(duration) {
2654
+ return queryOptions({
2655
+ queryKey: ["analytics", "discover-leaderboard", duration],
2656
+ queryFn: async ({ signal }) => {
2657
+ const response = await fetch(
2658
+ CONFIG.privateApiHost + `/private-api/leaderboard/${duration}`,
2659
+ { signal }
2660
+ );
2661
+ if (!response.ok) {
2662
+ throw new Error(`Failed to fetch leaderboard: ${response.status}`);
2663
+ }
2664
+ return response.json();
2665
+ }
2666
+ });
2667
+ }
2668
+ function getDiscoverCurationQueryOptions(duration) {
2669
+ return queryOptions({
2670
+ queryKey: ["analytics", "discover-curation", duration],
2671
+ queryFn: async ({ signal }) => {
2672
+ const response = await fetch(
2673
+ CONFIG.privateApiHost + `/private-api/curation/${duration}`,
2674
+ { signal }
2675
+ );
2676
+ if (!response.ok) {
2677
+ throw new Error(`Failed to fetch curation data: ${response.status}`);
2678
+ }
2679
+ const data = await response.json();
2680
+ const accounts = data.map((item) => item.account);
2681
+ const accountsResponse = await CONFIG.hiveClient.database.getAccounts(accounts);
2682
+ for (let index = 0; index < accountsResponse.length; index++) {
2683
+ const element = accountsResponse[index];
2684
+ const curator = data[index];
2685
+ const vestingShares = typeof element.vesting_shares === "string" ? element.vesting_shares : element.vesting_shares.toString();
2686
+ const receivedVestingShares = typeof element.received_vesting_shares === "string" ? element.received_vesting_shares : element.received_vesting_shares.toString();
2687
+ const delegatedVestingShares = typeof element.delegated_vesting_shares === "string" ? element.delegated_vesting_shares : element.delegated_vesting_shares.toString();
2688
+ const vestingWithdrawRate = typeof element.vesting_withdraw_rate === "string" ? element.vesting_withdraw_rate : element.vesting_withdraw_rate.toString();
2689
+ const effectiveVest = parseFloat(vestingShares) + parseFloat(receivedVestingShares) - parseFloat(delegatedVestingShares) - parseFloat(vestingWithdrawRate);
2690
+ curator.efficiency = curator.vests / effectiveVest;
2691
+ }
2692
+ data.sort((a, b) => b.efficiency - a.efficiency);
2693
+ return data;
2694
+ }
2695
+ });
2696
+ }
2697
+ function getPageStatsQueryOptions(url, dimensions = [], metrics = ["visitors", "pageviews", "visit_duration"], dateRange) {
2698
+ return queryOptions({
2699
+ queryKey: ["analytics", "page-stats", url, dimensions, metrics, dateRange],
2700
+ queryFn: async ({ signal }) => {
2701
+ const response = await fetch(CONFIG.privateApiHost + "/api/stats", {
2702
+ method: "POST",
2703
+ headers: {
2704
+ "Content-Type": "application/json"
2705
+ },
2706
+ body: JSON.stringify({
2707
+ metrics,
2708
+ url: encodeURIComponent(url),
2709
+ dimensions,
2710
+ date_range: dateRange
2711
+ }),
2712
+ signal
2713
+ });
2714
+ if (!response.ok) {
2715
+ throw new Error(`Failed to fetch page stats: ${response.status}`);
2716
+ }
2717
+ return response.json();
2718
+ },
2719
+ enabled: !!url
2720
+ });
2721
+ }
2722
+
2723
+ // src/modules/integrations/3speak/queries/index.ts
2724
+ var queries_exports2 = {};
2725
+ __export(queries_exports2, {
2726
+ getAccountTokenQueryOptions: () => getAccountTokenQueryOptions,
2727
+ getAccountVideosQueryOptions: () => getAccountVideosQueryOptions
2728
+ });
2729
+
2730
+ // src/modules/integrations/hivesigner/queries/index.ts
2731
+ var queries_exports = {};
2732
+ __export(queries_exports, {
2733
+ getDecodeMemoQueryOptions: () => getDecodeMemoQueryOptions
2734
+ });
2735
+ function getDecodeMemoQueryOptions(username, memo) {
2736
+ return queryOptions({
2737
+ queryKey: ["integrations", "hivesigner", "decode-memo", username],
2738
+ queryFn: async () => {
2739
+ const accessToken = getAccessToken(username);
2740
+ if (accessToken) {
2741
+ const hsClient = new hs.Client({
2742
+ accessToken
2743
+ });
2744
+ return hsClient.decode(memo);
2745
+ }
2746
+ }
2747
+ });
2748
+ }
2749
+
2750
+ // src/modules/integrations/hivesigner/index.ts
2751
+ var HiveSignerIntegration = {
2752
+ queries: queries_exports
2753
+ };
2754
+
2755
+ // src/modules/integrations/3speak/queries/get-account-token-query-options.ts
2756
+ function getAccountTokenQueryOptions(username) {
2757
+ return queryOptions({
2758
+ queryKey: ["integrations", "3speak", "authenticate", username],
2759
+ enabled: !!username,
2760
+ queryFn: async () => {
2761
+ if (!username) {
2762
+ throw new Error("[SDK][Integrations][3Speak] \u2013\xA0anon user");
2763
+ }
2764
+ const fetchApi = getBoundFetch();
2765
+ const response = await fetchApi(
2766
+ `https://studio.3speak.tv/mobile/login?username=${username}&hivesigner=true`,
2767
+ {
2768
+ headers: {
2769
+ "Content-Type": "application/json"
2770
+ }
2771
+ }
2772
+ );
2773
+ const memoQueryOptions = HiveSignerIntegration.queries.getDecodeMemoQueryOptions(
2774
+ username,
2775
+ (await response.json()).memo
2776
+ );
2777
+ await getQueryClient().prefetchQuery(memoQueryOptions);
2778
+ const { memoDecoded } = getQueryClient().getQueryData(
2779
+ memoQueryOptions.queryKey
2780
+ );
2781
+ return memoDecoded.replace("#", "");
2782
+ }
1028
2783
  });
1029
2784
  }
1030
- function useAccountRevokePosting(username, options) {
1031
- const queryClient = useQueryClient();
1032
- const { data } = useQuery(getAccountFullQueryOptions(username));
1033
- return useMutation({
1034
- mutationKey: ["accounts", "revoke-posting", data?.name],
1035
- mutationFn: async ({ accountName, type, key }) => {
1036
- if (!data) {
1037
- throw new Error(
1038
- "[SDK][Accounts] \u2013\xA0cannot revoke posting for anonymous user"
1039
- );
1040
- }
1041
- const posting = R4.pipe(
1042
- {},
1043
- R4.mergeDeep(data.posting)
2785
+ function getAccountVideosQueryOptions(username) {
2786
+ return queryOptions({
2787
+ queryKey: ["integrations", "3speak", "videos", username],
2788
+ enabled: !!username,
2789
+ queryFn: async () => {
2790
+ await getQueryClient().prefetchQuery(
2791
+ getAccountTokenQueryOptions(username)
1044
2792
  );
1045
- posting.account_auths = posting.account_auths.filter(
1046
- ([account]) => account !== accountName
2793
+ const token = getQueryClient().getQueryData(
2794
+ getAccountTokenQueryOptions(username).queryKey
1047
2795
  );
1048
- const operationBody = {
1049
- account: data.name,
1050
- posting,
1051
- memo_key: data.memo_key,
1052
- json_metadata: data.json_metadata
1053
- };
1054
- if (type === "key" && key) {
1055
- return CONFIG.hiveClient.broadcast.updateAccount(operationBody, key);
1056
- } else if (type === "keychain") {
1057
- return keychain_exports.broadcast(
1058
- data.name,
1059
- [["account_update", operationBody]],
1060
- "Active"
1061
- );
1062
- } else {
1063
- const params = {
1064
- callback: `https://ecency.com/@${data.name}/permissions`
1065
- };
1066
- return hs.sendOperation(
1067
- ["account_update", operationBody],
1068
- params,
1069
- () => {
1070
- }
1071
- );
1072
- }
1073
- },
1074
- onError: options.onError,
1075
- onSuccess: (resp, payload, ctx) => {
1076
- options.onSuccess?.(resp, payload, ctx);
1077
- queryClient.setQueryData(
1078
- getAccountFullQueryOptions(username).queryKey,
1079
- (data2) => ({
1080
- ...data2,
1081
- posting: {
1082
- ...data2?.posting,
1083
- account_auths: data2?.posting?.account_auths?.filter(
1084
- ([account]) => account !== payload.accountName
1085
- ) ?? []
2796
+ const fetchApi = getBoundFetch();
2797
+ const response = await fetchApi(
2798
+ `https://studio.3speak.tv/mobile/api/my-videos`,
2799
+ {
2800
+ headers: {
2801
+ "Content-Type": "application/json",
2802
+ Authorization: `Bearer ${token}`
1086
2803
  }
1087
- })
2804
+ }
1088
2805
  );
2806
+ return await response.json();
1089
2807
  }
1090
2808
  });
1091
2809
  }
1092
- function useAccountUpdateRecovery(username, options) {
1093
- const { data } = useQuery(getAccountFullQueryOptions(username));
1094
- return useMutation({
1095
- mutationKey: ["accounts", "recovery", data?.name],
1096
- mutationFn: async ({ accountName, type, key, email }) => {
1097
- if (!data) {
1098
- throw new Error(
1099
- "[SDK][Accounts] \u2013\xA0cannot change recovery for anonymous user"
1100
- );
1101
- }
1102
- const operationBody = {
1103
- account_to_recover: data.name,
1104
- new_recovery_account: accountName,
1105
- extensions: []
1106
- };
1107
- if (type === "ecency") {
2810
+
2811
+ // src/modules/integrations/3speak/index.ts
2812
+ var ThreeSpeakIntegration = {
2813
+ queries: queries_exports2
2814
+ };
2815
+ function getHivePoshLinksQueryOptions(username) {
2816
+ return queryOptions({
2817
+ queryKey: ["integrations", "hiveposh", "links", username],
2818
+ retry: false,
2819
+ // Don't retry on user not found errors
2820
+ queryFn: async () => {
2821
+ try {
1108
2822
  const fetchApi = getBoundFetch();
1109
- return fetchApi(CONFIG.privateApiHost + "/private-api/recoveries-add", {
1110
- method: "POST",
1111
- body: JSON.stringify({
1112
- code: getAccessToken(data.name),
1113
- email,
1114
- publicKeys: [
1115
- ...data.owner.key_auths,
1116
- ...data.active.key_auths,
1117
- ...data.posting.key_auths,
1118
- data.memo_key
1119
- ]
1120
- })
1121
- });
1122
- } else if (type === "key" && key) {
1123
- return CONFIG.hiveClient.broadcast.sendOperations(
1124
- [["change_recovery_account", operationBody]],
1125
- key
1126
- );
1127
- } else if (type === "keychain") {
1128
- return keychain_exports.broadcast(
1129
- data.name,
1130
- [["change_recovery_account", operationBody]],
1131
- "Active"
1132
- );
1133
- } else {
1134
- const params = {
1135
- callback: `https://ecency.com/@${data.name}/permissions`
1136
- };
1137
- return hs.sendOperation(
1138
- ["change_recovery_account", operationBody],
1139
- params,
1140
- () => {
2823
+ const response = await fetchApi(
2824
+ `https://hiveposh.com/api/v0/linked-accounts/${username}`,
2825
+ {
2826
+ headers: {
2827
+ "Content-Type": "application/json"
2828
+ }
1141
2829
  }
1142
2830
  );
2831
+ if (response.status === 400) {
2832
+ const errorData = await response.json().catch(() => ({}));
2833
+ if (errorData?.message === "User Not Connected") {
2834
+ return null;
2835
+ }
2836
+ }
2837
+ if (!response.ok) {
2838
+ return null;
2839
+ }
2840
+ const data = await response.json();
2841
+ return {
2842
+ twitter: {
2843
+ username: data.twitter_username,
2844
+ profile: data.twitter_profile
2845
+ },
2846
+ reddit: {
2847
+ username: data.reddit_username,
2848
+ profile: data.reddit_profile
2849
+ }
2850
+ };
2851
+ } catch (err) {
2852
+ return null;
1143
2853
  }
2854
+ }
2855
+ });
2856
+ }
2857
+ function getStatsQueryOptions({
2858
+ url,
2859
+ dimensions = [],
2860
+ metrics = ["visitors", "pageviews", "visit_duration"],
2861
+ enabled = true
2862
+ }) {
2863
+ return queryOptions({
2864
+ queryKey: ["integrations", "plausible", url, dimensions, metrics],
2865
+ queryFn: async () => {
2866
+ const fetchApi = getBoundFetch();
2867
+ const response = await fetchApi(`https://ecency.com/api/stats`, {
2868
+ method: "POST",
2869
+ body: JSON.stringify({
2870
+ metrics,
2871
+ url: encodeURIComponent(url),
2872
+ dimensions
2873
+ }),
2874
+ headers: {
2875
+ "Content-Type": "application/json"
2876
+ }
2877
+ });
2878
+ return await response.json();
1144
2879
  },
1145
- onError: options.onError,
1146
- onSuccess: options.onSuccess
2880
+ enabled: !!url && enabled
1147
2881
  });
1148
2882
  }
1149
- function useAccountRevokeKey(username, options) {
1150
- const { data: accountData } = useQuery(getAccountFullQueryOptions(username));
1151
- return useMutation({
1152
- mutationKey: ["accounts", "revoke-key", accountData?.name],
1153
- mutationFn: async ({ currentKey, revokingKey }) => {
1154
- if (!accountData) {
1155
- throw new Error(
1156
- "[SDK][Update password] \u2013 cannot update keys for anon user"
1157
- );
1158
- }
1159
- const prepareAuth = (keyName) => {
1160
- const auth = R4.clone(accountData[keyName]);
1161
- auth.key_auths = auth.key_auths.filter(
1162
- ([key]) => key !== revokingKey.toString()
1163
- );
1164
- return auth;
1165
- };
1166
- return CONFIG.hiveClient.broadcast.updateAccount(
1167
- {
1168
- account: accountData.name,
1169
- json_metadata: accountData.json_metadata,
1170
- owner: prepareAuth("owner"),
1171
- active: prepareAuth("active"),
1172
- posting: prepareAuth("posting"),
1173
- memo_key: accountData.memo_key
1174
- },
1175
- currentKey
2883
+ function getRcStatsQueryOptions() {
2884
+ return queryOptions({
2885
+ queryKey: ["resource-credits", "stats"],
2886
+ queryFn: async () => {
2887
+ const response = await CONFIG.hiveClient.call(
2888
+ "rc_api",
2889
+ "get_rc_stats",
2890
+ {}
1176
2891
  );
2892
+ return response.rc_stats;
2893
+ }
2894
+ });
2895
+ }
2896
+ function getAccountRcQueryOptions(username) {
2897
+ return queryOptions({
2898
+ queryKey: ["resource-credits", "account", username],
2899
+ queryFn: async () => {
2900
+ const rcClient = new RCAPI(CONFIG.hiveClient);
2901
+ return rcClient.findRCAccounts([username]);
1177
2902
  },
1178
- ...options
2903
+ enabled: !!username
1179
2904
  });
1180
2905
  }
1181
- function useSignOperationByKey(username) {
1182
- return useMutation({
1183
- mutationKey: ["operations", "sign", username],
1184
- mutationFn: ({
1185
- operation,
1186
- keyOrSeed
1187
- }) => {
2906
+ function getGameStatusCheckQueryOptions(username, gameType) {
2907
+ return queryOptions({
2908
+ queryKey: ["games", "status-check", gameType, username],
2909
+ enabled: !!username,
2910
+ queryFn: async () => {
1188
2911
  if (!username) {
1189
- throw new Error("[Operations][Sign] \u2013 cannot sign op with anon user");
1190
- }
1191
- let privateKey;
1192
- if (keyOrSeed.split(" ").length === 12) {
1193
- privateKey = PrivateKey.fromLogin(username, keyOrSeed, "active");
1194
- } else if (cryptoUtils.isWif(keyOrSeed)) {
1195
- privateKey = PrivateKey.fromString(keyOrSeed);
1196
- } else {
1197
- privateKey = PrivateKey.from(keyOrSeed);
2912
+ throw new Error("[SDK][Games] \u2013 anon user in status check");
1198
2913
  }
1199
- return CONFIG.hiveClient.broadcast.sendOperations(
1200
- [operation],
1201
- privateKey
2914
+ const fetchApi = getBoundFetch();
2915
+ const response = await fetchApi(
2916
+ CONFIG.privateApiHost + "/private-api/get-game",
2917
+ {
2918
+ method: "POST",
2919
+ body: JSON.stringify({
2920
+ game_type: gameType,
2921
+ code: getAccessToken(username)
2922
+ }),
2923
+ headers: {
2924
+ "Content-Type": "application/json"
2925
+ }
2926
+ }
1202
2927
  );
2928
+ return await response.json();
1203
2929
  }
1204
2930
  });
1205
2931
  }
1206
- function useSignOperationByKeychain(username, keyType = "Active") {
2932
+ function useGameClaim(username, gameType, key) {
2933
+ const { mutateAsync: recordActivity } = useRecordActivity(
2934
+ username,
2935
+ "spin-rolled"
2936
+ );
1207
2937
  return useMutation({
1208
- mutationKey: ["operations", "sign-keychain", username],
1209
- mutationFn: ({ operation }) => {
2938
+ mutationKey: ["games", "post", gameType, username],
2939
+ mutationFn: async () => {
1210
2940
  if (!username) {
1211
- throw new Error(
1212
- "[SDK][Keychain] \u2013\xA0cannot sign operation with anon user"
1213
- );
2941
+ throw new Error("[SDK][Games] \u2013 anon user in game post");
1214
2942
  }
1215
- return keychain_exports.broadcast(username, [operation], keyType);
2943
+ const fetchApi = getBoundFetch();
2944
+ const response = await fetchApi(
2945
+ CONFIG.privateApiHost + "/private-api/post-game",
2946
+ {
2947
+ method: "POST",
2948
+ body: JSON.stringify({
2949
+ game_type: gameType,
2950
+ code: getAccessToken(username),
2951
+ key
2952
+ }),
2953
+ headers: {
2954
+ "Content-Type": "application/json"
2955
+ }
2956
+ }
2957
+ );
2958
+ return await response.json();
2959
+ },
2960
+ onSuccess() {
2961
+ recordActivity();
1216
2962
  }
1217
2963
  });
1218
2964
  }
1219
- function useSignOperationByHivesigner(callbackUri = "/") {
1220
- return useMutation({
1221
- mutationKey: ["operations", "sign-hivesigner", callbackUri],
1222
- mutationFn: async ({ operation }) => {
1223
- return hs.sendOperation(operation, { callback: callbackUri }, () => {
1224
- });
2965
+ function getCommunitiesQueryOptions(sort, query, limit = 100, observer = void 0, enabled = true) {
2966
+ return queryOptions({
2967
+ queryKey: ["communities", "list", sort, query, limit],
2968
+ enabled,
2969
+ queryFn: async () => {
2970
+ const response = await CONFIG.hiveClient.call(
2971
+ "bridge",
2972
+ "list_communities",
2973
+ {
2974
+ last: "",
2975
+ limit,
2976
+ sort: sort === "hot" ? "rank" : sort,
2977
+ query: query ? query : null,
2978
+ observer
2979
+ }
2980
+ );
2981
+ return response ? sort === "hot" ? response.sort(() => Math.random() - 0.5) : response : [];
1225
2982
  }
1226
2983
  });
1227
2984
  }
1228
- function getChainPropertiesQueryOptions() {
2985
+ function getCommunityContextQueryOptions(username, communityName) {
1229
2986
  return queryOptions({
1230
- queryKey: ["operations", "chain-properties"],
2987
+ queryKey: ["community", "context", username, communityName],
2988
+ enabled: !!username && !!communityName,
1231
2989
  queryFn: async () => {
1232
- return await CONFIG.hiveClient.database.getChainProperties();
2990
+ const response = await CONFIG.hiveClient.call(
2991
+ "bridge",
2992
+ "get_community_context",
2993
+ {
2994
+ account: username,
2995
+ name: communityName
2996
+ }
2997
+ );
2998
+ return {
2999
+ role: response?.role ?? "guest",
3000
+ subscribed: response?.subscribed ?? false
3001
+ };
1233
3002
  }
1234
3003
  });
1235
3004
  }
1236
- function getTrendingTagsQueryOptions(limit = 20) {
3005
+ function getCommunitySubscribersQueryOptions(communityName) {
3006
+ return queryOptions({
3007
+ queryKey: ["communities", "subscribers", communityName],
3008
+ queryFn: async () => {
3009
+ const response = await CONFIG.hiveClient.call("bridge", "list_subscribers", {
3010
+ community: communityName
3011
+ });
3012
+ return response ?? [];
3013
+ },
3014
+ staleTime: 6e4
3015
+ });
3016
+ }
3017
+ function getAccountNotificationsInfiniteQueryOptions(account, limit) {
1237
3018
  return infiniteQueryOptions({
1238
- queryKey: ["posts", "trending-tags"],
1239
- queryFn: async ({ pageParam: { afterTag } }) => CONFIG.hiveClient.database.call("get_trending_tags", [afterTag, limit]).then(
1240
- (tags) => tags.filter((x) => x.name !== "").filter((x) => !x.name.startsWith("hive-")).map((x) => x.name)
1241
- ),
1242
- initialPageParam: { afterTag: "" },
1243
- getNextPageParam: (lastPage) => ({
1244
- afterTag: lastPage?.[lastPage?.length - 1]
1245
- }),
1246
- staleTime: Infinity,
1247
- refetchOnMount: true
3019
+ queryKey: ["communities", "account-notifications", account, limit],
3020
+ initialPageParam: null,
3021
+ queryFn: async ({ pageParam }) => {
3022
+ try {
3023
+ const response = await CONFIG.hiveClient.call("bridge", "account_notifications", {
3024
+ account,
3025
+ limit,
3026
+ last_id: pageParam ?? void 0
3027
+ });
3028
+ return response ?? [];
3029
+ } catch {
3030
+ return [];
3031
+ }
3032
+ },
3033
+ getNextPageParam: (lastPage) => lastPage?.length > 0 ? lastPage[lastPage.length - 1].id : null
1248
3034
  });
1249
3035
  }
1250
- function getFragmentsQueryOptions(username) {
3036
+ function getRewardedCommunitiesQueryOptions() {
1251
3037
  return queryOptions({
1252
- queryKey: ["posts", "fragments", username],
3038
+ queryKey: ["communities", "rewarded"],
1253
3039
  queryFn: async () => {
1254
- const fetchApi = getBoundFetch();
1255
- const response = await fetchApi(
1256
- CONFIG.privateApiHost + "/private-api/fragments",
3040
+ const response = await fetch(
3041
+ CONFIG.privateApiHost + "/private-api/rewarded-communities",
1257
3042
  {
1258
- method: "POST",
1259
- body: JSON.stringify({
1260
- code: getAccessToken(username)
1261
- }),
3043
+ method: "GET",
1262
3044
  headers: {
1263
3045
  "Content-Type": "application/json"
1264
3046
  }
1265
3047
  }
1266
3048
  );
3049
+ if (!response.ok) {
3050
+ throw new Error(`Failed to fetch rewarded communities: ${response.status}`);
3051
+ }
1267
3052
  return response.json();
1268
- },
1269
- enabled: !!username
3053
+ }
1270
3054
  });
1271
3055
  }
1272
- function getPromotedPostsQuery(type = "feed") {
1273
- return queryOptions({
1274
- queryKey: ["posts", "promoted", type],
1275
- queryFn: async () => {
1276
- const url = new URL(
1277
- CONFIG.privateApiHost + "/private-api/promoted-entries"
1278
- );
1279
- if (type === "waves") {
1280
- url.searchParams.append("short_content", "1");
1281
- }
1282
- const fetchApi = getBoundFetch();
1283
- const response = await fetchApi(url.toString(), {
1284
- method: "GET",
1285
- headers: {
1286
- "Content-Type": "application/json"
1287
- }
1288
- });
1289
- const data = await response.json();
1290
- return data;
3056
+
3057
+ // src/modules/communities/types/community.ts
3058
+ var ROLES = /* @__PURE__ */ ((ROLES2) => {
3059
+ ROLES2["OWNER"] = "owner";
3060
+ ROLES2["ADMIN"] = "admin";
3061
+ ROLES2["MOD"] = "mod";
3062
+ ROLES2["MEMBER"] = "member";
3063
+ ROLES2["GUEST"] = "guest";
3064
+ ROLES2["MUTED"] = "muted";
3065
+ return ROLES2;
3066
+ })(ROLES || {});
3067
+ var roleMap = {
3068
+ ["owner" /* OWNER */]: [
3069
+ "admin" /* ADMIN */,
3070
+ "mod" /* MOD */,
3071
+ "member" /* MEMBER */,
3072
+ "guest" /* GUEST */,
3073
+ "muted" /* MUTED */
3074
+ ],
3075
+ ["admin" /* ADMIN */]: ["mod" /* MOD */, "member" /* MEMBER */, "guest" /* GUEST */, "muted" /* MUTED */],
3076
+ ["mod" /* MOD */]: ["member" /* MEMBER */, "guest" /* GUEST */, "muted" /* MUTED */]
3077
+ };
3078
+
3079
+ // src/modules/communities/utils/index.ts
3080
+ function getCommunityType(name, type_id) {
3081
+ if (name.startsWith("hive-3") || type_id === 3) return "Council";
3082
+ if (name.startsWith("hive-2") || type_id === 2) return "Journal";
3083
+ return "Topic";
3084
+ }
3085
+ function getCommunityPermissions({
3086
+ communityType,
3087
+ userRole,
3088
+ subscribed
3089
+ }) {
3090
+ const canPost = (() => {
3091
+ if (userRole === "muted" /* MUTED */) return false;
3092
+ if (communityType === "Topic") return true;
3093
+ return ["owner" /* OWNER */, "admin" /* ADMIN */, "mod" /* MOD */, "member" /* MEMBER */].includes(
3094
+ userRole
3095
+ );
3096
+ })();
3097
+ const canComment = (() => {
3098
+ if (userRole === "muted" /* MUTED */) return false;
3099
+ switch (communityType) {
3100
+ case "Topic":
3101
+ return true;
3102
+ case "Journal":
3103
+ return userRole !== "guest" /* GUEST */ || subscribed;
3104
+ case "Council":
3105
+ return canPost;
1291
3106
  }
1292
- });
3107
+ })();
3108
+ const isModerator = ["owner" /* OWNER */, "admin" /* ADMIN */, "mod" /* MOD */].includes(userRole);
3109
+ return {
3110
+ canPost,
3111
+ canComment,
3112
+ isModerator
3113
+ };
1293
3114
  }
1294
- function useAddFragment(username) {
1295
- return useMutation({
1296
- mutationKey: ["posts", "add-fragment", username],
1297
- mutationFn: async ({ title, body }) => {
1298
- const fetchApi = getBoundFetch();
1299
- const response = await fetchApi(
1300
- CONFIG.privateApiHost + "/private-api/fragments-add",
3115
+ function getNotificationsUnreadCountQueryOptions(activeUsername) {
3116
+ return queryOptions({
3117
+ queryKey: ["notifications", "unread", activeUsername],
3118
+ queryFn: async () => {
3119
+ const response = await fetch(
3120
+ `${CONFIG.privateApiHost}/private-api/notifications/unread`,
1301
3121
  {
1302
3122
  method: "POST",
1303
- body: JSON.stringify({
1304
- code: getAccessToken(username),
1305
- title,
1306
- body
1307
- }),
3123
+ body: JSON.stringify({ code: getAccessToken(activeUsername) }),
1308
3124
  headers: {
1309
3125
  "Content-Type": "application/json"
1310
3126
  }
1311
3127
  }
1312
3128
  );
1313
- return response.json();
3129
+ const data = await response.json();
3130
+ return data.count;
1314
3131
  },
1315
- onSuccess(response) {
1316
- getQueryClient().setQueryData(
1317
- getFragmentsQueryOptions(username).queryKey,
1318
- (data) => [response, ...data ?? []]
1319
- );
1320
- }
3132
+ enabled: !!activeUsername,
3133
+ initialData: 0,
3134
+ refetchInterval: 6e4
1321
3135
  });
1322
3136
  }
1323
- function useEditFragment(username, fragmentId) {
1324
- return useMutation({
1325
- mutationKey: ["posts", "edit-fragment", username, fragmentId],
1326
- mutationFn: async ({ title, body }) => {
1327
- const fetchApi = getBoundFetch();
1328
- const response = await fetchApi(
1329
- CONFIG.privateApiHost + "/private-api/fragments-update",
3137
+ function getNotificationsInfiniteQueryOptions(activeUsername, filter = void 0) {
3138
+ return infiniteQueryOptions({
3139
+ queryKey: ["notifications", activeUsername, filter],
3140
+ queryFn: async ({ pageParam }) => {
3141
+ const data = {
3142
+ code: getAccessToken(activeUsername),
3143
+ filter,
3144
+ since: pageParam,
3145
+ user: void 0
3146
+ };
3147
+ const response = await fetch(
3148
+ CONFIG.privateApiHost + "/private-api/notifications",
1330
3149
  {
1331
3150
  method: "POST",
1332
- body: JSON.stringify({
1333
- code: getAccessToken(username),
1334
- id: fragmentId,
1335
- title,
1336
- body
1337
- }),
1338
3151
  headers: {
1339
3152
  "Content-Type": "application/json"
1340
- }
3153
+ },
3154
+ body: JSON.stringify(data)
1341
3155
  }
1342
3156
  );
1343
3157
  return response.json();
1344
3158
  },
1345
- onSuccess(response) {
1346
- getQueryClient().setQueryData(
1347
- getFragmentsQueryOptions(username).queryKey,
1348
- (data) => {
1349
- if (!data) {
1350
- return [];
1351
- }
1352
- const index = data.findIndex(({ id }) => id === fragmentId);
1353
- if (index >= 0) {
1354
- data[index] = response;
3159
+ enabled: !!activeUsername,
3160
+ initialData: { pages: [], pageParams: [] },
3161
+ initialPageParam: "",
3162
+ getNextPageParam: (lastPage) => lastPage?.[lastPage.length - 1]?.id ?? "",
3163
+ refetchOnMount: true
3164
+ });
3165
+ }
3166
+
3167
+ // src/modules/notifications/enums/notification-filter.ts
3168
+ var NotificationFilter = /* @__PURE__ */ ((NotificationFilter2) => {
3169
+ NotificationFilter2["VOTES"] = "rvotes";
3170
+ NotificationFilter2["MENTIONS"] = "mentions";
3171
+ NotificationFilter2["FAVORITES"] = "nfavorites";
3172
+ NotificationFilter2["BOOKMARKS"] = "nbookmarks";
3173
+ NotificationFilter2["FOLLOWS"] = "follows";
3174
+ NotificationFilter2["REPLIES"] = "replies";
3175
+ NotificationFilter2["REBLOGS"] = "reblogs";
3176
+ NotificationFilter2["TRANSFERS"] = "transfers";
3177
+ NotificationFilter2["DELEGATIONS"] = "delegations";
3178
+ return NotificationFilter2;
3179
+ })(NotificationFilter || {});
3180
+
3181
+ // src/modules/notifications/enums/notify-types.ts
3182
+ var NotifyTypes = /* @__PURE__ */ ((NotifyTypes2) => {
3183
+ NotifyTypes2[NotifyTypes2["VOTE"] = 1] = "VOTE";
3184
+ NotifyTypes2[NotifyTypes2["MENTION"] = 2] = "MENTION";
3185
+ NotifyTypes2[NotifyTypes2["FOLLOW"] = 3] = "FOLLOW";
3186
+ NotifyTypes2[NotifyTypes2["COMMENT"] = 4] = "COMMENT";
3187
+ NotifyTypes2[NotifyTypes2["RE_BLOG"] = 5] = "RE_BLOG";
3188
+ NotifyTypes2[NotifyTypes2["TRANSFERS"] = 6] = "TRANSFERS";
3189
+ NotifyTypes2[NotifyTypes2["FAVORITES"] = 13] = "FAVORITES";
3190
+ NotifyTypes2[NotifyTypes2["BOOKMARKS"] = 15] = "BOOKMARKS";
3191
+ NotifyTypes2["ALLOW_NOTIFY"] = "ALLOW_NOTIFY";
3192
+ return NotifyTypes2;
3193
+ })(NotifyTypes || {});
3194
+ var ALL_NOTIFY_TYPES = [
3195
+ 1 /* VOTE */,
3196
+ 2 /* MENTION */,
3197
+ 3 /* FOLLOW */,
3198
+ 4 /* COMMENT */,
3199
+ 5 /* RE_BLOG */,
3200
+ 6 /* TRANSFERS */,
3201
+ 13 /* FAVORITES */,
3202
+ 15 /* BOOKMARKS */
3203
+ ];
3204
+ var NotificationViewType = /* @__PURE__ */ ((NotificationViewType2) => {
3205
+ NotificationViewType2["ALL"] = "All";
3206
+ NotificationViewType2["UNREAD"] = "Unread";
3207
+ NotificationViewType2["READ"] = "Read";
3208
+ return NotificationViewType2;
3209
+ })(NotificationViewType || {});
3210
+
3211
+ // src/modules/notifications/queries/get-notifications-settings-query-options.ts
3212
+ function getNotificationsSettingsQueryOptions(activeUsername) {
3213
+ return queryOptions({
3214
+ queryKey: ["notifications", "settings", activeUsername],
3215
+ queryFn: async () => {
3216
+ let token = activeUsername + "-web";
3217
+ const response = await fetch(
3218
+ CONFIG.privateApiHost + "/private-api/detail-device",
3219
+ {
3220
+ body: JSON.stringify({
3221
+ code: getAccessToken(activeUsername),
3222
+ username: activeUsername,
3223
+ token
3224
+ }),
3225
+ method: "POST",
3226
+ headers: {
3227
+ "Content-Type": "application/json"
1355
3228
  }
1356
- return [...data];
1357
3229
  }
1358
3230
  );
3231
+ if (!response.ok) {
3232
+ throw new Error(`Failed to fetch notification settings: ${response.status}`);
3233
+ }
3234
+ return response.json();
3235
+ },
3236
+ enabled: !!activeUsername,
3237
+ refetchOnMount: false,
3238
+ initialData: () => {
3239
+ const wasMutedPreviously = typeof window !== "undefined" ? localStorage.getItem("notifications") !== "true" : false;
3240
+ return {
3241
+ status: 0,
3242
+ system: "web",
3243
+ allows_notify: 0,
3244
+ notify_types: wasMutedPreviously ? [] : [
3245
+ 4 /* COMMENT */,
3246
+ 3 /* FOLLOW */,
3247
+ 2 /* MENTION */,
3248
+ 13 /* FAVORITES */,
3249
+ 15 /* BOOKMARKS */,
3250
+ 1 /* VOTE */,
3251
+ 5 /* RE_BLOG */,
3252
+ 6 /* TRANSFERS */
3253
+ ]
3254
+ };
1359
3255
  }
1360
3256
  });
1361
3257
  }
1362
- function useRemoveFragment(username, fragmentId) {
1363
- return useMutation({
1364
- mutationKey: ["posts", "remove-fragment", username],
1365
- mutationFn: async () => {
1366
- const fetchApi = getBoundFetch();
1367
- return fetchApi(CONFIG.privateApiHost + "/private-api/fragments-delete", {
1368
- method: "POST",
1369
- body: JSON.stringify({
1370
- code: getAccessToken(username),
1371
- id: fragmentId
1372
- }),
3258
+ function getAnnouncementsQueryOptions() {
3259
+ return queryOptions({
3260
+ queryKey: ["notifications", "announcements"],
3261
+ queryFn: async () => {
3262
+ const response = await fetch(CONFIG.privateApiHost + "/private-api/announcements", {
3263
+ method: "GET",
1373
3264
  headers: {
1374
3265
  "Content-Type": "application/json"
1375
3266
  }
1376
3267
  });
3268
+ if (!response.ok) {
3269
+ throw new Error(`Failed to fetch announcements: ${response.status}`);
3270
+ }
3271
+ const data = await response.json();
3272
+ return data || [];
1377
3273
  },
1378
- onSuccess() {
1379
- getQueryClient().setQueryData(
1380
- getFragmentsQueryOptions(username).queryKey,
1381
- (data) => [...data ?? []].filter(({ id }) => id !== fragmentId)
1382
- );
1383
- }
3274
+ staleTime: 36e5
1384
3275
  });
1385
3276
  }
1386
-
1387
- // src/modules/analytics/mutations/index.ts
1388
- var mutations_exports = {};
1389
- __export(mutations_exports, {
1390
- useRecordActivity: () => useRecordActivity
1391
- });
1392
- function useRecordActivity(username, activityType) {
1393
- return useMutation({
1394
- mutationKey: ["analytics", activityType],
1395
- mutationFn: async () => {
1396
- if (!activityType) {
1397
- throw new Error("[SDK][Analytics] \u2013 no activity type provided");
3277
+ function getProposalQueryOptions(id) {
3278
+ return queryOptions({
3279
+ queryKey: ["proposals", "proposal", id],
3280
+ queryFn: async () => {
3281
+ const r = await CONFIG.hiveClient.call("condenser_api", "find_proposals", [[id]]);
3282
+ const proposal = r[0];
3283
+ if (new Date(proposal.start_date) < /* @__PURE__ */ new Date() && new Date(proposal.end_date) >= /* @__PURE__ */ new Date()) {
3284
+ proposal.status = "active";
3285
+ } else if (new Date(proposal.end_date) < /* @__PURE__ */ new Date()) {
3286
+ proposal.status = "expired";
3287
+ } else {
3288
+ proposal.status = "inactive";
1398
3289
  }
1399
- const fetchApi = getBoundFetch();
1400
- await fetchApi(CONFIG.plausibleHost + "/api/event", {
1401
- method: "POST",
1402
- headers: {
1403
- "Content-Type": "application/json"
1404
- },
1405
- body: JSON.stringify({
1406
- name: activityType,
1407
- url: window.location.href,
1408
- domain: window.location.host,
1409
- props: {
1410
- username
1411
- }
1412
- })
3290
+ return proposal;
3291
+ }
3292
+ });
3293
+ }
3294
+ function getProposalsQueryOptions() {
3295
+ return queryOptions({
3296
+ queryKey: ["proposals", "list"],
3297
+ queryFn: async () => {
3298
+ const response = await CONFIG.hiveClient.call("database_api", "list_proposals", {
3299
+ start: [-1],
3300
+ limit: 500,
3301
+ order: "by_total_votes",
3302
+ order_direction: "descending",
3303
+ status: "all"
1413
3304
  });
3305
+ const proposals = response.proposals;
3306
+ const expired = proposals.filter((x) => x.status === "expired");
3307
+ const others = proposals.filter((x) => x.status !== "expired");
3308
+ return [...others, ...expired];
1414
3309
  }
1415
3310
  });
1416
3311
  }
1417
-
1418
- // src/modules/integrations/3speak/queries/index.ts
1419
- var queries_exports2 = {};
1420
- __export(queries_exports2, {
1421
- getAccountTokenQueryOptions: () => getAccountTokenQueryOptions,
1422
- getAccountVideosQueryOptions: () => getAccountVideosQueryOptions
1423
- });
1424
-
1425
- // src/modules/integrations/hivesigner/queries/index.ts
1426
- var queries_exports = {};
1427
- __export(queries_exports, {
1428
- getDecodeMemoQueryOptions: () => getDecodeMemoQueryOptions
1429
- });
1430
- function getDecodeMemoQueryOptions(username, memo) {
3312
+ function getProposalVotesInfiniteQueryOptions(proposalId, voter, limit) {
3313
+ return infiniteQueryOptions({
3314
+ queryKey: ["proposals", "votes", proposalId, voter, limit],
3315
+ initialPageParam: voter,
3316
+ refetchOnMount: true,
3317
+ staleTime: 0,
3318
+ // Always refetch on mount
3319
+ queryFn: async ({ pageParam }) => {
3320
+ const startParam = pageParam ?? voter;
3321
+ const response = await CONFIG.hiveClient.call("condenser_api", "list_proposal_votes", [
3322
+ [proposalId, startParam],
3323
+ limit,
3324
+ "by_proposal_voter"
3325
+ ]);
3326
+ const list = response.filter((x) => x.proposal?.proposal_id === proposalId).map((x) => ({ id: x.id, voter: x.voter }));
3327
+ const rawAccounts = await CONFIG.hiveClient.database.getAccounts(list.map((l) => l.voter));
3328
+ const accounts = parseAccounts(rawAccounts);
3329
+ const page = list.map((i) => ({
3330
+ ...i,
3331
+ voterAccount: accounts.find((a) => i.voter === a.name)
3332
+ }));
3333
+ return page;
3334
+ },
3335
+ getNextPageParam: (lastPage) => {
3336
+ const last = lastPage?.[lastPage.length - 1];
3337
+ return last?.voter ?? void 0;
3338
+ }
3339
+ });
3340
+ }
3341
+ function getUserProposalVotesQueryOptions(voter) {
1431
3342
  return queryOptions({
1432
- queryKey: ["integrations", "hivesigner", "decode-memo", username],
3343
+ queryKey: ["proposals", "votes", "by-user", voter],
3344
+ enabled: !!voter && voter !== "",
3345
+ staleTime: 60 * 1e3,
3346
+ // Cache for 1 minute
1433
3347
  queryFn: async () => {
1434
- const accessToken = getAccessToken(username);
1435
- if (accessToken) {
1436
- const hsClient = new hs.Client({
1437
- accessToken
1438
- });
1439
- return hsClient.decode(memo);
3348
+ if (!voter || voter === "") {
3349
+ return [];
1440
3350
  }
3351
+ const response = await CONFIG.hiveClient.call("database_api", "list_proposal_votes", {
3352
+ start: [voter],
3353
+ limit: 1e3,
3354
+ order: "by_voter_proposal",
3355
+ order_direction: "ascending",
3356
+ status: "votable"
3357
+ });
3358
+ const userVotes = (response.proposal_votes || []).filter((vote) => vote.voter === voter);
3359
+ return userVotes;
1441
3360
  }
1442
3361
  });
1443
3362
  }
1444
-
1445
- // src/modules/integrations/hivesigner/index.ts
1446
- var HiveSignerIntegration = {
1447
- queries: queries_exports
1448
- };
1449
-
1450
- // src/modules/integrations/3speak/queries/get-account-token-query-options.ts
1451
- function getAccountTokenQueryOptions(username) {
3363
+ function getVestingDelegationsQueryOptions(username, from, limit = 50) {
1452
3364
  return queryOptions({
1453
- queryKey: ["integrations", "3speak", "authenticate", username],
1454
- enabled: !!username,
1455
- queryFn: async () => {
1456
- if (!username) {
1457
- throw new Error("[SDK][Integrations][3Speak] \u2013\xA0anon user");
3365
+ queryKey: ["wallet", "vesting-delegations", username, from, limit],
3366
+ queryFn: () => CONFIG.hiveClient.database.call("get_vesting_delegations", [
3367
+ username,
3368
+ from,
3369
+ limit
3370
+ ]),
3371
+ enabled: !!username
3372
+ });
3373
+ }
3374
+ function getConversionRequestsQueryOptions(account) {
3375
+ return queryOptions({
3376
+ queryKey: ["wallet", "conversion-requests", account],
3377
+ queryFn: () => CONFIG.hiveClient.database.call("get_conversion_requests", [
3378
+ account
3379
+ ]),
3380
+ select: (data) => data.sort((a, b) => a.requestid - b.requestid)
3381
+ });
3382
+ }
3383
+ function getCollateralizedConversionRequestsQueryOptions(account) {
3384
+ return queryOptions({
3385
+ queryKey: ["wallet", "collateralized-conversion-requests", account],
3386
+ queryFn: () => CONFIG.hiveClient.database.call("get_collateralized_conversion_requests", [
3387
+ account
3388
+ ]),
3389
+ select: (data) => data.sort((a, b) => a.requestid - b.requestid)
3390
+ });
3391
+ }
3392
+ function getSavingsWithdrawFromQueryOptions(account) {
3393
+ return queryOptions({
3394
+ queryKey: ["wallet", "savings-withdraw", account],
3395
+ queryFn: () => CONFIG.hiveClient.database.call("get_savings_withdraw_from", [
3396
+ account
3397
+ ]),
3398
+ select: (data) => data.sort((a, b) => a.request_id - b.request_id)
3399
+ });
3400
+ }
3401
+ function getWithdrawRoutesQueryOptions(account) {
3402
+ return queryOptions({
3403
+ queryKey: ["wallet", "withdraw-routes", account],
3404
+ queryFn: () => CONFIG.hiveClient.database.call("get_withdraw_routes", [
3405
+ account,
3406
+ "outgoing"
3407
+ ])
3408
+ });
3409
+ }
3410
+ function getOpenOrdersQueryOptions(user) {
3411
+ return queryOptions({
3412
+ queryKey: ["wallet", "open-orders", user],
3413
+ queryFn: () => CONFIG.hiveClient.call("condenser_api", "get_open_orders", [
3414
+ user
3415
+ ]),
3416
+ select: (data) => data.sort((a, b) => a.orderid - b.orderid),
3417
+ enabled: !!user
3418
+ });
3419
+ }
3420
+ function getOutgoingRcDelegationsInfiniteQueryOptions(username, limit = 100) {
3421
+ return infiniteQueryOptions({
3422
+ queryKey: ["wallet", "outgoing-rc-delegations", username, limit],
3423
+ initialPageParam: null,
3424
+ queryFn: async ({ pageParam }) => {
3425
+ const response = await CONFIG.hiveClient.call("rc_api", "list_rc_direct_delegations", {
3426
+ start: [username, pageParam ?? ""],
3427
+ limit
3428
+ }).then((r) => r);
3429
+ let delegations = response.rc_direct_delegations || [];
3430
+ if (pageParam) {
3431
+ delegations = delegations.filter((delegation) => delegation.to !== pageParam);
1458
3432
  }
1459
- const fetchApi = getBoundFetch();
1460
- const response = await fetchApi(
1461
- `https://studio.3speak.tv/mobile/login?username=${username}&hivesigner=true`,
1462
- {
1463
- headers: {
1464
- "Content-Type": "application/json"
1465
- }
1466
- }
1467
- );
1468
- const memoQueryOptions = HiveSignerIntegration.queries.getDecodeMemoQueryOptions(
1469
- username,
1470
- (await response.json()).memo
1471
- );
1472
- await getQueryClient().prefetchQuery(memoQueryOptions);
1473
- const { memoDecoded } = getQueryClient().getQueryData(
1474
- memoQueryOptions.queryKey
3433
+ return delegations;
3434
+ },
3435
+ getNextPageParam: (lastPage) => lastPage.length === limit ? lastPage[lastPage.length - 1].to : null
3436
+ });
3437
+ }
3438
+ function getReceivedVestingSharesQueryOptions(username) {
3439
+ return queryOptions({
3440
+ queryKey: ["wallet", "received-vesting-shares", username],
3441
+ queryFn: async () => {
3442
+ const response = await fetch(
3443
+ CONFIG.privateApiHost + `/private-api/received-vesting/${username}`
1475
3444
  );
1476
- return memoDecoded.replace("#", "");
3445
+ if (!response.ok) {
3446
+ throw new Error(`Failed to fetch received vesting shares: ${response.status}`);
3447
+ }
3448
+ const data = await response.json();
3449
+ return data.list;
1477
3450
  }
1478
3451
  });
1479
3452
  }
1480
- function getAccountVideosQueryOptions(username) {
3453
+ function getWitnessesInfiniteQueryOptions(limit) {
3454
+ return infiniteQueryOptions({
3455
+ queryKey: ["witnesses", "list", limit],
3456
+ initialPageParam: "",
3457
+ queryFn: async ({ pageParam }) => CONFIG.hiveClient.call("condenser_api", "get_witnesses_by_vote", [
3458
+ pageParam,
3459
+ limit
3460
+ ]),
3461
+ getNextPageParam: (lastPage) => {
3462
+ const last = lastPage?.[lastPage.length - 1];
3463
+ return last ? last.owner : void 0;
3464
+ }
3465
+ });
3466
+ }
3467
+ function getOrderBookQueryOptions(limit = 500) {
1481
3468
  return queryOptions({
1482
- queryKey: ["integrations", "3speak", "videos", username],
1483
- enabled: !!username,
3469
+ queryKey: ["market", "order-book", limit],
3470
+ queryFn: () => CONFIG.hiveClient.call("condenser_api", "get_order_book", [
3471
+ limit
3472
+ ])
3473
+ });
3474
+ }
3475
+ function getMarketStatisticsQueryOptions() {
3476
+ return queryOptions({
3477
+ queryKey: ["market", "statistics"],
3478
+ queryFn: () => CONFIG.hiveClient.call("condenser_api", "get_ticker", [])
3479
+ });
3480
+ }
3481
+ function getMarketHistoryQueryOptions(seconds, startDate, endDate) {
3482
+ const formatDate = (date) => {
3483
+ return date.toISOString().replace(/\.\d{3}Z$/, "");
3484
+ };
3485
+ return queryOptions({
3486
+ queryKey: ["market", "history", seconds, startDate.getTime(), endDate.getTime()],
3487
+ queryFn: () => CONFIG.hiveClient.call("condenser_api", "get_market_history", [
3488
+ seconds,
3489
+ formatDate(startDate),
3490
+ formatDate(endDate)
3491
+ ])
3492
+ });
3493
+ }
3494
+ function getHiveHbdStatsQueryOptions() {
3495
+ return queryOptions({
3496
+ queryKey: ["market", "hive-hbd-stats"],
1484
3497
  queryFn: async () => {
1485
- await getQueryClient().prefetchQuery(
1486
- getAccountTokenQueryOptions(username)
3498
+ const stats = await CONFIG.hiveClient.call(
3499
+ "condenser_api",
3500
+ "get_ticker",
3501
+ []
1487
3502
  );
1488
- const token = getQueryClient().getQueryData(
1489
- getAccountTokenQueryOptions(username).queryKey
3503
+ const now = /* @__PURE__ */ new Date();
3504
+ const oneDayAgo = new Date(now.getTime() - 864e5);
3505
+ const formatDate = (date) => {
3506
+ return date.toISOString().replace(/\.\d{3}Z$/, "");
3507
+ };
3508
+ const dayChange = await CONFIG.hiveClient.call(
3509
+ "condenser_api",
3510
+ "get_market_history",
3511
+ [86400, formatDate(oneDayAgo), formatDate(now)]
1490
3512
  );
1491
- const fetchApi = getBoundFetch();
1492
- const response = await fetchApi(
1493
- `https://studio.3speak.tv/mobile/api/my-videos`,
3513
+ const result = {
3514
+ price: +stats.latest,
3515
+ close: dayChange[0] ? dayChange[0].non_hive.open / dayChange[0].hive.open : 0,
3516
+ high: dayChange[0] ? dayChange[0].non_hive.high / dayChange[0].hive.high : 0,
3517
+ low: dayChange[0] ? dayChange[0].non_hive.low / dayChange[0].hive.low : 0,
3518
+ percent: dayChange[0] ? 100 - dayChange[0].non_hive.open / dayChange[0].hive.open * 100 / +stats.latest : 0,
3519
+ totalFromAsset: stats.hive_volume.split(" ")[0],
3520
+ totalToAsset: stats.hbd_volume.split(" ")[0]
3521
+ };
3522
+ return result;
3523
+ }
3524
+ });
3525
+ }
3526
+ function getMarketDataQueryOptions(coin, vsCurrency, fromTs, toTs) {
3527
+ return queryOptions({
3528
+ queryKey: ["market", "data", coin, vsCurrency, fromTs, toTs],
3529
+ queryFn: async ({ signal }) => {
3530
+ const url = `https://api.coingecko.com/api/v3/coins/${coin}/market_chart/range?vs_currency=${vsCurrency}&from=${fromTs}&to=${toTs}`;
3531
+ const response = await fetch(url, { signal });
3532
+ if (!response.ok) {
3533
+ throw new Error(`Failed to fetch market data: ${response.status}`);
3534
+ }
3535
+ return response.json();
3536
+ }
3537
+ });
3538
+ }
3539
+ function getPointsQueryOptions(username, filter = 0) {
3540
+ return queryOptions({
3541
+ queryKey: ["points", username, filter],
3542
+ queryFn: async () => {
3543
+ if (!username) {
3544
+ throw new Error("Get points query \u2013 username wasn't provided");
3545
+ }
3546
+ const name = username.replace("@", "");
3547
+ const pointsResponse = await fetch(CONFIG.privateApiHost + "/private-api/points", {
3548
+ method: "POST",
3549
+ headers: {
3550
+ "Content-Type": "application/json"
3551
+ },
3552
+ body: JSON.stringify({ username: name })
3553
+ });
3554
+ if (!pointsResponse.ok) {
3555
+ throw new Error(`Failed to fetch points: ${pointsResponse.status}`);
3556
+ }
3557
+ const points = await pointsResponse.json();
3558
+ const transactionsResponse = await fetch(
3559
+ CONFIG.privateApiHost + "/private-api/point-list",
1494
3560
  {
3561
+ method: "POST",
1495
3562
  headers: {
1496
- "Content-Type": "application/json",
1497
- Authorization: `Bearer ${token}`
1498
- }
3563
+ "Content-Type": "application/json"
3564
+ },
3565
+ body: JSON.stringify({ username: name, type: filter })
1499
3566
  }
1500
3567
  );
1501
- return await response.json();
3568
+ if (!transactionsResponse.ok) {
3569
+ throw new Error(`Failed to fetch point transactions: ${transactionsResponse.status}`);
3570
+ }
3571
+ const transactions = await transactionsResponse.json();
3572
+ return {
3573
+ points: points.points,
3574
+ uPoints: points.unclaimed_points,
3575
+ transactions
3576
+ };
3577
+ },
3578
+ staleTime: 3e4,
3579
+ refetchOnMount: true,
3580
+ enabled: !!username
3581
+ });
3582
+ }
3583
+ function searchQueryOptions(q, sort, hideLow, since, scroll_id, votes) {
3584
+ return queryOptions({
3585
+ queryKey: ["search", q, sort, hideLow, since, scroll_id, votes],
3586
+ queryFn: async () => {
3587
+ const data = { q, sort, hide_low: hideLow };
3588
+ if (since) data.since = since;
3589
+ if (scroll_id) data.scroll_id = scroll_id;
3590
+ if (votes) data.votes = votes;
3591
+ const response = await fetch(CONFIG.privateApiHost + "/search-api/search", {
3592
+ method: "POST",
3593
+ headers: {
3594
+ "Content-Type": "application/json"
3595
+ },
3596
+ body: JSON.stringify(data)
3597
+ });
3598
+ if (!response.ok) {
3599
+ throw new Error(`Search failed: ${response.status}`);
3600
+ }
3601
+ return response.json();
1502
3602
  }
1503
3603
  });
1504
3604
  }
1505
-
1506
- // src/modules/integrations/3speak/index.ts
1507
- var ThreeSpeakIntegration = {
1508
- queries: queries_exports2
1509
- };
1510
- function getHivePoshLinksQueryOptions(username) {
3605
+ function getControversialRisingInfiniteQueryOptions(what, tag, enabled = true) {
3606
+ return infiniteQueryOptions({
3607
+ queryKey: ["search", "controversial-rising", what, tag],
3608
+ initialPageParam: { sid: void 0, hasNextPage: true },
3609
+ queryFn: async ({ pageParam }) => {
3610
+ if (!pageParam.hasNextPage) {
3611
+ return {
3612
+ hits: 0,
3613
+ took: 0,
3614
+ results: []
3615
+ };
3616
+ }
3617
+ let sinceDate;
3618
+ const now = /* @__PURE__ */ new Date();
3619
+ switch (tag) {
3620
+ case "today":
3621
+ sinceDate = new Date(now.getTime() - 24 * 60 * 60 * 1e3);
3622
+ break;
3623
+ case "week":
3624
+ sinceDate = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1e3);
3625
+ break;
3626
+ case "month":
3627
+ sinceDate = new Date(now.getTime() - 30 * 24 * 60 * 60 * 1e3);
3628
+ break;
3629
+ case "year":
3630
+ sinceDate = new Date(now.getTime() - 365 * 24 * 60 * 60 * 1e3);
3631
+ break;
3632
+ default:
3633
+ sinceDate = void 0;
3634
+ }
3635
+ const q = "* type:post";
3636
+ const sort = what === "rising" ? "children" : what;
3637
+ const since = sinceDate ? sinceDate.toISOString().split(".")[0] : void 0;
3638
+ const hideLow = "0";
3639
+ const votes = tag === "today" ? 50 : 200;
3640
+ const data = { q, sort, hide_low: hideLow };
3641
+ if (since) data.since = since;
3642
+ if (pageParam.sid) data.scroll_id = pageParam.sid;
3643
+ data.votes = votes;
3644
+ const response = await fetch(CONFIG.privateApiHost + "/search-api/search", {
3645
+ method: "POST",
3646
+ headers: {
3647
+ "Content-Type": "application/json"
3648
+ },
3649
+ body: JSON.stringify(data)
3650
+ });
3651
+ if (!response.ok) {
3652
+ throw new Error(`Search failed: ${response.status}`);
3653
+ }
3654
+ return response.json();
3655
+ },
3656
+ getNextPageParam: (resp) => {
3657
+ return {
3658
+ sid: resp?.scroll_id,
3659
+ hasNextPage: resp.results.length > 0
3660
+ };
3661
+ },
3662
+ enabled
3663
+ });
3664
+ }
3665
+ function buildQuery(entry, retry = 3) {
3666
+ const { json_metadata, permlink } = entry;
3667
+ let q = "*";
3668
+ q += ` -dporn type:post`;
3669
+ let tags;
3670
+ if (json_metadata && json_metadata.tags && Array.isArray(json_metadata.tags)) {
3671
+ tags = json_metadata.tags.filter((tag) => tag && tag !== "").filter((tag) => !tag.startsWith("hive-")).filter((_tag, ind) => ind < +retry).join(",");
3672
+ }
3673
+ if (tags && tags.length > 0) {
3674
+ q += ` tag:${tags}`;
3675
+ } else {
3676
+ const fperm = permlink.split("-");
3677
+ tags = fperm.filter((part) => part !== "").filter((part) => !/^-?\d+$/.test(part)).filter((part) => part.length > 2).join(",");
3678
+ q += ` tag:${tags}`;
3679
+ }
3680
+ return q;
3681
+ }
3682
+ function getSimilarEntriesQueryOptions(entry) {
3683
+ const query = buildQuery(entry);
1511
3684
  return queryOptions({
1512
- queryKey: ["integrations", "hiveposh", "links", username],
3685
+ queryKey: ["search", "similar-entries", entry.author, entry.permlink, query],
1513
3686
  queryFn: async () => {
1514
- const fetchApi = getBoundFetch();
1515
- const response = await fetchApi(
1516
- `https://hiveposh.com/api/v0/linked-accounts/${username}`,
1517
- {
1518
- headers: {
1519
- "Content-Type": "application/json"
1520
- }
1521
- }
1522
- );
1523
- const data = await response.json();
1524
- return {
1525
- twitter: {
1526
- username: data.twitter_username,
1527
- profile: data.twitter_profile
3687
+ const data = {
3688
+ q: query,
3689
+ sort: "newest",
3690
+ hide_low: "0"
3691
+ };
3692
+ const response = await fetch(CONFIG.privateApiHost + "/search-api/search", {
3693
+ method: "POST",
3694
+ headers: {
3695
+ "Content-Type": "application/json"
1528
3696
  },
1529
- reddit: {
1530
- username: data.reddit_username,
1531
- profile: data.reddit_profile
3697
+ body: JSON.stringify(data)
3698
+ });
3699
+ if (!response.ok) {
3700
+ throw new Error(`Search failed: ${response.status}`);
3701
+ }
3702
+ const searchResponse = await response.json();
3703
+ const rawEntries = searchResponse.results.filter(
3704
+ (r) => r.permlink !== entry.permlink && r.tags.indexOf("nsfw") === -1
3705
+ );
3706
+ const entries = [];
3707
+ for (const result of rawEntries) {
3708
+ if (entries.find((y) => y.author === result.author) === void 0) {
3709
+ entries.push(result);
1532
3710
  }
1533
- };
3711
+ }
3712
+ return entries.slice(0, 3);
1534
3713
  }
1535
3714
  });
1536
3715
  }
1537
- function getStatsQueryOptions({
1538
- url,
1539
- dimensions = [],
1540
- metrics = ["visitors", "pageviews", "visit_duration"],
1541
- enabled = true
1542
- }) {
3716
+ function getSearchAccountQueryOptions(q, limit = 5, random = false) {
1543
3717
  return queryOptions({
1544
- queryKey: ["integrations", "plausible", url, dimensions, metrics],
3718
+ queryKey: ["search", "account", q, limit],
1545
3719
  queryFn: async () => {
1546
- const fetchApi = getBoundFetch();
1547
- const response = await fetchApi(`https://ecency.com/api/stats`, {
3720
+ const data = { q, limit, random: +random };
3721
+ const response = await fetch(CONFIG.privateApiHost + "/search-api/search-account", {
1548
3722
  method: "POST",
1549
- body: JSON.stringify({
1550
- metrics,
1551
- url: encodeURIComponent(url),
1552
- dimensions
1553
- }),
1554
3723
  headers: {
1555
3724
  "Content-Type": "application/json"
1556
- }
3725
+ },
3726
+ body: JSON.stringify(data)
1557
3727
  });
1558
- return await response.json();
3728
+ if (!response.ok) {
3729
+ throw new Error(`Failed to search accounts: ${response.status}`);
3730
+ }
3731
+ return response.json();
1559
3732
  },
1560
- enabled: !!url && enabled
3733
+ enabled: !!q
1561
3734
  });
1562
3735
  }
1563
- function getRcStatsQueryOptions() {
3736
+ function getSearchTopicsQueryOptions(q, limit = 20, random = false) {
1564
3737
  return queryOptions({
1565
- queryKey: ["resource-credits", "stats"],
3738
+ queryKey: ["search", "topics", q],
1566
3739
  queryFn: async () => {
1567
- const response = await CONFIG.hiveClient.call(
1568
- "rc_api",
1569
- "get_rc_stats",
1570
- {}
1571
- );
1572
- return response.rc_stats;
1573
- }
3740
+ const data = { q, limit, random: +random };
3741
+ const response = await fetch(CONFIG.privateApiHost + "/search-api/search-tag", {
3742
+ method: "POST",
3743
+ headers: {
3744
+ "Content-Type": "application/json"
3745
+ },
3746
+ body: JSON.stringify(data)
3747
+ });
3748
+ if (!response.ok) {
3749
+ throw new Error(`Failed to search topics: ${response.status}`);
3750
+ }
3751
+ return response.json();
3752
+ },
3753
+ enabled: !!q
1574
3754
  });
1575
3755
  }
1576
- function getAccountRcQueryOptions(username) {
1577
- return queryOptions({
1578
- queryKey: ["resource-credits", "account", username],
1579
- queryFn: async () => {
1580
- const rcClient = new RCAPI(CONFIG.hiveClient);
1581
- return rcClient.findRCAccounts([username]);
3756
+ function getSearchApiInfiniteQueryOptions(q, sort, hideLow, since, votes) {
3757
+ return infiniteQueryOptions({
3758
+ queryKey: ["search", "api", q, sort, hideLow, since, votes],
3759
+ queryFn: async ({ pageParam }) => {
3760
+ const payload = { q, sort, hide_low: hideLow };
3761
+ if (since) {
3762
+ payload.since = since;
3763
+ }
3764
+ if (pageParam) {
3765
+ payload.scroll_id = pageParam;
3766
+ }
3767
+ if (votes !== void 0) {
3768
+ payload.votes = votes;
3769
+ }
3770
+ const response = await fetch(CONFIG.privateApiHost + "/search-api/search", {
3771
+ method: "POST",
3772
+ headers: {
3773
+ "Content-Type": "application/json"
3774
+ },
3775
+ body: JSON.stringify(payload)
3776
+ });
3777
+ if (!response.ok) {
3778
+ throw new Error(`Search failed: ${response.status}`);
3779
+ }
3780
+ return response.json();
1582
3781
  },
1583
- enabled: !!username
3782
+ initialPageParam: void 0,
3783
+ getNextPageParam: (lastPage) => lastPage?.scroll_id,
3784
+ enabled: !!q
1584
3785
  });
1585
3786
  }
1586
- function getGameStatusCheckQueryOptions(username, gameType) {
3787
+ function getSearchPathQueryOptions(q) {
1587
3788
  return queryOptions({
1588
- queryKey: ["games", "status-check", gameType, username],
1589
- enabled: !!username,
3789
+ queryKey: ["search", "path", q],
1590
3790
  queryFn: async () => {
1591
- if (!username) {
1592
- throw new Error("[SDK][Games] \u2013 anon user in status check");
3791
+ const response = await fetch(CONFIG.privateApiHost + "/search-api/search-path", {
3792
+ method: "POST",
3793
+ headers: {
3794
+ "Content-Type": "application/json"
3795
+ },
3796
+ body: JSON.stringify({ q })
3797
+ });
3798
+ if (!response.ok) {
3799
+ throw new Error(`Search path failed: ${response.status}`);
1593
3800
  }
1594
- const fetchApi = getBoundFetch();
1595
- const response = await fetchApi(
1596
- CONFIG.privateApiHost + "/private-api/get-game",
1597
- {
1598
- method: "POST",
1599
- body: JSON.stringify({
1600
- game_type: gameType,
1601
- code: getAccessToken(username)
1602
- }),
1603
- headers: {
1604
- "Content-Type": "application/json"
1605
- }
1606
- }
1607
- );
1608
- return await response.json();
3801
+ const data = await response.json();
3802
+ if (data?.length > 0) {
3803
+ return data;
3804
+ }
3805
+ return [q];
1609
3806
  }
1610
3807
  });
1611
3808
  }
1612
- function useGameClaim(username, gameType, key) {
1613
- const { mutateAsync: recordActivity } = useRecordActivity(
1614
- username,
1615
- "spin-rolled"
1616
- );
1617
- return useMutation({
1618
- mutationKey: ["games", "post", gameType, username],
1619
- mutationFn: async () => {
1620
- if (!username) {
1621
- throw new Error("[SDK][Games] \u2013 anon user in game post");
3809
+ function getBoostPlusPricesQueryOptions(accessToken) {
3810
+ return queryOptions({
3811
+ queryKey: ["promotions", "boost-plus-prices"],
3812
+ queryFn: async () => {
3813
+ if (!accessToken) {
3814
+ return [];
3815
+ }
3816
+ const response = await fetch(CONFIG.privateApiHost + "/private-api/boost-plus-price", {
3817
+ method: "POST",
3818
+ headers: {
3819
+ "Content-Type": "application/json"
3820
+ },
3821
+ body: JSON.stringify({ code: accessToken })
3822
+ });
3823
+ if (!response.ok) {
3824
+ throw new Error(`Failed to fetch boost plus prices: ${response.status}`);
1622
3825
  }
1623
- const fetchApi = getBoundFetch();
1624
- const response = await fetchApi(
1625
- CONFIG.privateApiHost + "/private-api/post-game",
1626
- {
1627
- method: "POST",
1628
- body: JSON.stringify({
1629
- game_type: gameType,
1630
- code: getAccessToken(username),
1631
- key
1632
- }),
1633
- headers: {
1634
- "Content-Type": "application/json"
1635
- }
1636
- }
1637
- );
1638
3826
  return await response.json();
1639
3827
  },
1640
- onSuccess() {
1641
- recordActivity();
1642
- }
3828
+ staleTime: Infinity,
3829
+ refetchOnMount: true,
3830
+ enabled: !!accessToken
1643
3831
  });
1644
3832
  }
1645
- function getCommunitiesQueryOptions(sort, query, limit = 100, observer = void 0, enabled = true) {
3833
+ function getPromotePriceQueryOptions(accessToken) {
1646
3834
  return queryOptions({
1647
- queryKey: ["communities", "list", sort, query, limit],
1648
- enabled,
3835
+ queryKey: ["promotions", "promote-price"],
1649
3836
  queryFn: async () => {
1650
- const response = await CONFIG.hiveClient.call(
1651
- "bridge",
1652
- "list_communities",
1653
- {
1654
- last: "",
1655
- limit,
1656
- sort: sort === "hot" ? "rank" : sort,
1657
- query: query ? query : null,
1658
- observer
1659
- }
1660
- );
1661
- return response ? sort === "hot" ? response.sort(() => Math.random() - 0.5) : response : [];
1662
- }
3837
+ const response = await fetch(CONFIG.privateApiHost + "/private-api/promote-price", {
3838
+ method: "POST",
3839
+ headers: {
3840
+ "Content-Type": "application/json"
3841
+ },
3842
+ body: JSON.stringify({ code: accessToken })
3843
+ });
3844
+ if (!response.ok) {
3845
+ throw new Error(`Failed to fetch promote prices: ${response.status}`);
3846
+ }
3847
+ return await response.json();
3848
+ },
3849
+ enabled: !!accessToken
1663
3850
  });
1664
3851
  }
1665
- function getCommunityContextQueryOptions(username, communityName) {
3852
+ function getBoostPlusAccountPricesQueryOptions(account, accessToken) {
1666
3853
  return queryOptions({
1667
- queryKey: ["community", "context", username, communityName],
1668
- enabled: !!username && !!communityName,
3854
+ queryKey: ["promotions", "boost-plus-accounts", account],
1669
3855
  queryFn: async () => {
1670
- const response = await CONFIG.hiveClient.call(
1671
- "bridge",
1672
- "get_community_context",
1673
- {
1674
- account: username,
1675
- name: communityName
1676
- }
1677
- );
1678
- return {
1679
- role: response?.role ?? "guest",
1680
- subscribed: response?.subscribed ?? false
1681
- };
1682
- }
3856
+ if (!accessToken || !account) {
3857
+ return null;
3858
+ }
3859
+ const response = await fetch(CONFIG.privateApiHost + "/private-api/boosted-plus-account", {
3860
+ method: "POST",
3861
+ headers: {
3862
+ "Content-Type": "application/json"
3863
+ },
3864
+ body: JSON.stringify({ code: accessToken, account })
3865
+ });
3866
+ if (!response.ok) {
3867
+ throw new Error(`Failed to fetch boost plus account prices: ${response.status}`);
3868
+ }
3869
+ const responseData = await response.json();
3870
+ return responseData ? {
3871
+ account: responseData.account,
3872
+ expires: new Date(responseData.expires)
3873
+ } : null;
3874
+ },
3875
+ enabled: !!account && !!accessToken
1683
3876
  });
1684
3877
  }
1685
3878
 
1686
- // src/modules/communities/types/community.ts
1687
- var ROLES = /* @__PURE__ */ ((ROLES2) => {
1688
- ROLES2["OWNER"] = "owner";
1689
- ROLES2["ADMIN"] = "admin";
1690
- ROLES2["MOD"] = "mod";
1691
- ROLES2["MEMBER"] = "member";
1692
- ROLES2["GUEST"] = "guest";
1693
- ROLES2["MUTED"] = "muted";
1694
- return ROLES2;
1695
- })(ROLES || {});
1696
- var roleMap = {
1697
- ["owner" /* OWNER */]: [
1698
- "admin" /* ADMIN */,
1699
- "mod" /* MOD */,
1700
- "member" /* MEMBER */,
1701
- "guest" /* GUEST */,
1702
- "muted" /* MUTED */
1703
- ],
1704
- ["admin" /* ADMIN */]: ["mod" /* MOD */, "member" /* MEMBER */, "guest" /* GUEST */, "muted" /* MUTED */],
1705
- ["mod" /* MOD */]: ["member" /* MEMBER */, "guest" /* GUEST */, "muted" /* MUTED */]
1706
- };
1707
-
1708
- // src/modules/communities/utils/index.ts
1709
- function getCommunityType(name, type_id) {
1710
- if (name.startsWith("hive-3") || type_id === 3) return "Council";
1711
- if (name.startsWith("hive-2") || type_id === 2) return "Journal";
1712
- return "Topic";
1713
- }
1714
- function getCommunityPermissions({
1715
- communityType,
1716
- userRole,
1717
- subscribed
1718
- }) {
1719
- const canPost = (() => {
1720
- if (userRole === "muted" /* MUTED */) return false;
1721
- if (communityType === "Topic") return true;
1722
- return ["owner" /* OWNER */, "admin" /* ADMIN */, "mod" /* MOD */, "member" /* MEMBER */].includes(
1723
- userRole
1724
- );
1725
- })();
1726
- const canComment = (() => {
1727
- if (userRole === "muted" /* MUTED */) return false;
1728
- switch (communityType) {
1729
- case "Topic":
1730
- return true;
1731
- case "Journal":
1732
- return userRole !== "guest" /* GUEST */ || subscribed;
1733
- case "Council":
1734
- return canPost;
1735
- }
1736
- })();
1737
- const isModerator = ["owner" /* OWNER */, "admin" /* ADMIN */, "mod" /* MOD */].includes(userRole);
1738
- return {
1739
- canPost,
1740
- canComment,
1741
- isModerator
1742
- };
1743
- }
1744
-
1745
- export { CONFIG, ConfigManager, mutations_exports as EcencyAnalytics, EcencyQueriesManager, HiveSignerIntegration, keychain_exports as Keychain, NaiMap, ROLES, Symbol2 as Symbol, ThreeSpeakIntegration, broadcastJson, buildProfileMetadata, checkUsernameWalletsPendingQueryOptions, decodeObj, dedupeAndSortKeyAuths, encodeObj, extractAccountProfile, getAccessToken, getAccountFullQueryOptions, getAccountPendingRecoveryQueryOptions, getAccountRcQueryOptions, getAccountRecoveriesQueryOptions, getAccountSubscriptionsQueryOptions, getActiveAccountBookmarksQueryOptions, getActiveAccountFavouritesQueryOptions, getBoundFetch, getChainPropertiesQueryOptions, getCommunitiesQueryOptions, getCommunityContextQueryOptions, getCommunityPermissions, getCommunityType, getDynamicPropsQueryOptions, getFragmentsQueryOptions, getGameStatusCheckQueryOptions, getHivePoshLinksQueryOptions, getLoginType, getPostingKey, getPromotedPostsQuery, getQueryClient, getRcStatsQueryOptions, getRefreshToken, getRelationshipBetweenAccountsQueryOptions, getSearchAccountsByUsernameQueryOptions, getStatsQueryOptions, getTrendingTagsQueryOptions, getUser, makeQueryClient, parseAsset, parseProfileMetadata, roleMap, useAccountFavouriteAdd, useAccountFavouriteDelete, useAccountRelationsUpdate, useAccountRevokeKey, useAccountRevokePosting, useAccountUpdate, useAccountUpdateKeyAuths, useAccountUpdatePassword, useAccountUpdateRecovery, useAddFragment, useBookmarkAdd, useBookmarkDelete, useBroadcastMutation, useEditFragment, useGameClaim, useRemoveFragment, useSignOperationByHivesigner, useSignOperationByKey, useSignOperationByKeychain };
3879
+ export { ACCOUNT_OPERATION_GROUPS, ALL_ACCOUNT_OPERATIONS, ALL_NOTIFY_TYPES, CONFIG, ConfigManager, mutations_exports as EcencyAnalytics, EcencyQueriesManager, HiveSignerIntegration, keychain_exports as Keychain, NaiMap, NotificationFilter, NotificationViewType, NotifyTypes, ROLES, SortOrder, Symbol2 as Symbol, ThreeSpeakIntegration, broadcastJson, buildProfileMetadata, checkUsernameWalletsPendingQueryOptions, decodeObj, dedupeAndSortKeyAuths, encodeObj, extractAccountProfile, getAccessToken, getAccountFullQueryOptions, getAccountNotificationsInfiniteQueryOptions, getAccountPendingRecoveryQueryOptions, getAccountPostsInfiniteQueryOptions, getAccountRcQueryOptions, getAccountRecoveriesQueryOptions, getAccountSubscriptionsQueryOptions, getAccountVoteHistoryInfiniteQueryOptions, getAccountsQueryOptions, getActiveAccountBookmarksQueryOptions, getActiveAccountFavouritesQueryOptions, getAnnouncementsQueryOptions, getBoostPlusAccountPricesQueryOptions, getBoostPlusPricesQueryOptions, getBotsQueryOptions, getBoundFetch, getChainPropertiesQueryOptions, getCollateralizedConversionRequestsQueryOptions, getCommentHistoryQueryOptions, getCommunitiesQueryOptions, getCommunityContextQueryOptions, getCommunityPermissions, getCommunitySubscribersQueryOptions, getCommunityType, getControversialRisingInfiniteQueryOptions, getConversionRequestsQueryOptions, getDeletedEntryQueryOptions, getDiscoverCurationQueryOptions, getDiscoverLeaderboardQueryOptions, getDiscussionsQueryOptions, getDraftsQueryOptions, getDynamicPropsQueryOptions, getEntryActiveVotesQueryOptions, getFollowCountQueryOptions, getFollowingQueryOptions, getFragmentsQueryOptions, getFriendsInfiniteQueryOptions, getGalleryImagesQueryOptions, getGameStatusCheckQueryOptions, getHiveHbdStatsQueryOptions, getHivePoshLinksQueryOptions, getImagesQueryOptions, getLoginType, getMarketDataQueryOptions, getMarketHistoryQueryOptions, getMarketStatisticsQueryOptions, getMutedUsersQueryOptions, getNotificationsInfiniteQueryOptions, getNotificationsSettingsQueryOptions, getNotificationsUnreadCountQueryOptions, getOpenOrdersQueryOptions, getOrderBookQueryOptions, getOutgoingRcDelegationsInfiniteQueryOptions, getPageStatsQueryOptions, getPointsQueryOptions, getPostHeaderQueryOptions, getPostQueryOptions, getPostTipsQueryOptions, getPostingKey, getPostsRankedInfiniteQueryOptions, getPromotePriceQueryOptions, getPromotedPostsQuery, getProposalQueryOptions, getProposalVotesInfiniteQueryOptions, getProposalsQueryOptions, getQueryClient, getRcStatsQueryOptions, getReblogsQueryOptions, getReceivedVestingSharesQueryOptions, getReferralsInfiniteQueryOptions, getReferralsStatsQueryOptions, getRefreshToken, getRelationshipBetweenAccountsQueryOptions, getRewardedCommunitiesQueryOptions, getSavingsWithdrawFromQueryOptions, getSchedulesQueryOptions, getSearchAccountQueryOptions, getSearchAccountsByUsernameQueryOptions, getSearchApiInfiniteQueryOptions, getSearchFriendsQueryOptions, getSearchPathQueryOptions, getSearchTopicsQueryOptions, getSimilarEntriesQueryOptions, getStatsQueryOptions, getTransactionsInfiniteQueryOptions, getTrendingTagsQueryOptions, getUser, getUserProposalVotesQueryOptions, getVestingDelegationsQueryOptions, getVisibleFirstLevelThreadItems, getWavesByHostQueryOptions, getWavesByTagQueryOptions, getWavesFollowingQueryOptions, getWavesTrendingTagsQueryOptions, getWithdrawRoutesQueryOptions, getWitnessesInfiniteQueryOptions, lookupAccountsQueryOptions, makeQueryClient, mapThreadItemsToWaveEntries, normalizeWaveEntryFromApi, parseAccounts, parseAsset, parseProfileMetadata, roleMap, searchQueryOptions, sortDiscussions, toEntryArray, useAccountFavouriteAdd, useAccountFavouriteDelete, useAccountRelationsUpdate, useAccountRevokeKey, useAccountRevokePosting, useAccountUpdate, useAccountUpdateKeyAuths, useAccountUpdatePassword, useAccountUpdateRecovery, useAddFragment, useBookmarkAdd, useBookmarkDelete, useBroadcastMutation, useEditFragment, useGameClaim, useRecordActivity, useRemoveFragment, useSignOperationByHivesigner, useSignOperationByKey, useSignOperationByKeychain };
1746
3880
  //# sourceMappingURL=index.mjs.map
1747
3881
  //# sourceMappingURL=index.mjs.map