@lightsparkdev/lightspark-sdk 0.1.6

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.
Files changed (223) hide show
  1. package/.fossa.yml +6 -0
  2. package/.prettierrc +1 -0
  3. package/.turbo/turbo-build.log +19 -0
  4. package/.turbo/turbo-lint.log +3 -0
  5. package/CHANGELOG.md +49 -0
  6. package/LICENSE +201 -0
  7. package/README.md +137 -0
  8. package/dist/Withdrawal-17e1c8af.d.ts +1672 -0
  9. package/dist/Withdrawal-27a4d10d.d.ts +1672 -0
  10. package/dist/chunk-3VRI7CHE.js +5508 -0
  11. package/dist/chunk-AGEUDR2V.js +4498 -0
  12. package/dist/chunk-N27QHRE4.js +5508 -0
  13. package/dist/client-3bba3f64.d.ts +1302 -0
  14. package/dist/index.cjs +6633 -0
  15. package/dist/index.d.ts +15 -0
  16. package/dist/index.js +1177 -0
  17. package/dist/objects/index.cjs +5347 -0
  18. package/dist/objects/index.d.ts +3 -0
  19. package/dist/objects/index.js +88 -0
  20. package/examples/node-scripts/authHelpers.ts +20 -0
  21. package/examples/node-scripts/createInvoice.ts +64 -0
  22. package/examples/node-scripts/example.ts +288 -0
  23. package/examples/node-scripts/getAccountDashboard.ts +24 -0
  24. package/examples/node-scripts/getNodeChannels.ts +34 -0
  25. package/examples/node-scripts/internalAuthHelpers.ts +26 -0
  26. package/examples/node-scripts/internal_example.ts +296 -0
  27. package/examples/node-scripts/package-lock.json +887 -0
  28. package/examples/node-scripts/package.json +22 -0
  29. package/examples/node-scripts/prettyPrintJsonForDocs.ts +62 -0
  30. package/examples/node-scripts/tsconfig.json +27 -0
  31. package/examples/oauth-example/README.md +19 -0
  32. package/examples/oauth-example/package-lock.json +16071 -0
  33. package/examples/oauth-example/package.json +50 -0
  34. package/examples/oauth-example/public/favicon.ico +0 -0
  35. package/examples/oauth-example/public/index.html +43 -0
  36. package/examples/oauth-example/public/logo192.png +0 -0
  37. package/examples/oauth-example/public/logo512.png +0 -0
  38. package/examples/oauth-example/public/manifest.json +25 -0
  39. package/examples/oauth-example/public/robots.txt +3 -0
  40. package/examples/oauth-example/src/App.css +7 -0
  41. package/examples/oauth-example/src/App.test.tsx +12 -0
  42. package/examples/oauth-example/src/App.tsx +16 -0
  43. package/examples/oauth-example/src/auth/AuthContext.ts +8 -0
  44. package/examples/oauth-example/src/auth/AuthProvider.tsx +44 -0
  45. package/examples/oauth-example/src/auth/RequireAuth.tsx +19 -0
  46. package/examples/oauth-example/src/auth/oauthProvider.ts +35 -0
  47. package/examples/oauth-example/src/components/Button.tsx +39 -0
  48. package/examples/oauth-example/src/components/CurrencyAmount.tsx +117 -0
  49. package/examples/oauth-example/src/components/Dashboard.tsx +158 -0
  50. package/examples/oauth-example/src/components/Table.tsx +22 -0
  51. package/examples/oauth-example/src/hooks/useAccountInfo.tsx +31 -0
  52. package/examples/oauth-example/src/icons/BitcoinB.tsx +20 -0
  53. package/examples/oauth-example/src/icons/Icon.tsx +121 -0
  54. package/examples/oauth-example/src/icons/Satoshi.tsx +28 -0
  55. package/examples/oauth-example/src/index.css +13 -0
  56. package/examples/oauth-example/src/index.tsx +23 -0
  57. package/examples/oauth-example/src/lightsparkclient/LightsparkClientContext.ts +10 -0
  58. package/examples/oauth-example/src/lightsparkclient/LightsparkClientProvider.tsx +53 -0
  59. package/examples/oauth-example/src/logo.svg +1 -0
  60. package/examples/oauth-example/src/pages/DashboardPage.tsx +71 -0
  61. package/examples/oauth-example/src/pages/LoginPage.tsx +63 -0
  62. package/examples/oauth-example/src/react-app-env.d.ts +1 -0
  63. package/examples/oauth-example/src/reportWebVitals.ts +15 -0
  64. package/examples/oauth-example/src/routes/index.tsx +15 -0
  65. package/examples/oauth-example/src/setupTests.ts +5 -0
  66. package/examples/oauth-example/src/utils/currency.ts +483 -0
  67. package/examples/oauth-example/tsconfig.json +20 -0
  68. package/examples/streaming-wallet-extension/.fossa.yml +6 -0
  69. package/examples/streaming-wallet-extension/README.md +17 -0
  70. package/examples/streaming-wallet-extension/craco.config.js +58 -0
  71. package/examples/streaming-wallet-extension/package-lock.json +18260 -0
  72. package/examples/streaming-wallet-extension/package.json +77 -0
  73. package/examples/streaming-wallet-extension/public/index.html +24 -0
  74. package/examples/streaming-wallet-extension/public/lightspark_full.png +0 -0
  75. package/examples/streaming-wallet-extension/public/lightspark_icon_circle.png +0 -0
  76. package/examples/streaming-wallet-extension/public/manifest.json +43 -0
  77. package/examples/streaming-wallet-extension/public/robots.txt +3 -0
  78. package/examples/streaming-wallet-extension/src/App.css +53 -0
  79. package/examples/streaming-wallet-extension/src/App.tsx +425 -0
  80. package/examples/streaming-wallet-extension/src/auth/AccountStorage.ts +28 -0
  81. package/examples/streaming-wallet-extension/src/auth/DemoAccountProvider.ts +99 -0
  82. package/examples/streaming-wallet-extension/src/auth/StreamingDemoCredentials.ts +10 -0
  83. package/examples/streaming-wallet-extension/src/background/PaymentStrategy.ts +36 -0
  84. package/examples/streaming-wallet-extension/src/background/PlaybackRange.ts +31 -0
  85. package/examples/streaming-wallet-extension/src/background/StreamingInvoiceHolder.ts +33 -0
  86. package/examples/streaming-wallet-extension/src/background/TransactionObserver.ts +66 -0
  87. package/examples/streaming-wallet-extension/src/background/VideoPlaybackRanges.ts +38 -0
  88. package/examples/streaming-wallet-extension/src/background/VideoProgressCache.ts +87 -0
  89. package/examples/streaming-wallet-extension/src/background/background.ts +145 -0
  90. package/examples/streaming-wallet-extension/src/background/messageHandling.ts +185 -0
  91. package/examples/streaming-wallet-extension/src/common/datetimes.ts +28 -0
  92. package/examples/streaming-wallet-extension/src/common/settings.ts +12 -0
  93. package/examples/streaming-wallet-extension/src/common/storage.ts +8 -0
  94. package/examples/streaming-wallet-extension/src/common/streamingTabs.ts +27 -0
  95. package/examples/streaming-wallet-extension/src/common/types.tsx +23 -0
  96. package/examples/streaming-wallet-extension/src/components/CirclePlusIcon.tsx +19 -0
  97. package/examples/streaming-wallet-extension/src/components/CurrencyAmount.tsx +110 -0
  98. package/examples/streaming-wallet-extension/src/components/CurrencyAmountRaw.tsx +195 -0
  99. package/examples/streaming-wallet-extension/src/components/LeftArrow.tsx +21 -0
  100. package/examples/streaming-wallet-extension/src/components/Loading.tsx +151 -0
  101. package/examples/streaming-wallet-extension/src/components/StreamingTransactionChip.tsx +95 -0
  102. package/examples/streaming-wallet-extension/src/components/TransactionRow.tsx +93 -0
  103. package/examples/streaming-wallet-extension/src/contentscript/content.ts +123 -0
  104. package/examples/streaming-wallet-extension/src/contentscript/lightsparkDemoDom.tsx +113 -0
  105. package/examples/streaming-wallet-extension/src/contentscript/videoElementParsers.ts +92 -0
  106. package/examples/streaming-wallet-extension/src/index.css +16 -0
  107. package/examples/streaming-wallet-extension/src/index.tsx +11 -0
  108. package/examples/streaming-wallet-extension/src/lightsparkClientProvider.tsx +26 -0
  109. package/examples/streaming-wallet-extension/src/react-app-env.d.ts +1 -0
  110. package/examples/streaming-wallet-extension/src/types/Messages.ts +17 -0
  111. package/examples/streaming-wallet-extension/tsconfig.json +20 -0
  112. package/package.json +87 -0
  113. package/src/auth/AccountTokenAuthProvider.ts +37 -0
  114. package/src/auth/index.ts +3 -0
  115. package/src/client.ts +759 -0
  116. package/src/graphql/BitcoinFeeEstimate.ts +13 -0
  117. package/src/graphql/CreateApiToken.ts +22 -0
  118. package/src/graphql/CreateInvoice.ts +18 -0
  119. package/src/graphql/CreateNodeWalletAddress.ts +13 -0
  120. package/src/graphql/CurrentAccount.ts +13 -0
  121. package/src/graphql/DecodeInvoice.ts +16 -0
  122. package/src/graphql/DeleteApiToken.ts +13 -0
  123. package/src/graphql/FundNode.ts +18 -0
  124. package/src/graphql/LightningFeeEstimateForInvoice.ts +21 -0
  125. package/src/graphql/LightningFeeEstimateForNode.ts +21 -0
  126. package/src/graphql/MultiNodeDashboard.ts +118 -0
  127. package/src/graphql/PayInvoice.ts +29 -0
  128. package/src/graphql/RecoverNodeSigningKey.ts +15 -0
  129. package/src/graphql/RequestWithdrawal.ts +25 -0
  130. package/src/graphql/SendPayment.ts +29 -0
  131. package/src/graphql/SingleNodeDashboard.ts +116 -0
  132. package/src/graphql/TransactionSubscription.ts +16 -0
  133. package/src/graphql/TransactionsForNode.ts +42 -0
  134. package/src/index.ts +5 -0
  135. package/src/objects/Account.ts +1222 -0
  136. package/src/objects/AccountToApiTokensConnection.ts +50 -0
  137. package/src/objects/AccountToChannelsConnection.ts +35 -0
  138. package/src/objects/AccountToNodesConnection.ts +62 -0
  139. package/src/objects/AccountToPaymentRequestsConnection.ts +50 -0
  140. package/src/objects/AccountToTransactionsConnection.ts +112 -0
  141. package/src/objects/ApiToken.ts +80 -0
  142. package/src/objects/BitcoinNetwork.ts +19 -0
  143. package/src/objects/BlockchainBalance.ts +102 -0
  144. package/src/objects/Channel.ts +283 -0
  145. package/src/objects/ChannelClosingTransaction.ts +150 -0
  146. package/src/objects/ChannelFees.ts +34 -0
  147. package/src/objects/ChannelOpeningTransaction.ts +150 -0
  148. package/src/objects/ChannelStatus.ts +25 -0
  149. package/src/objects/ChannelToTransactionsConnection.ts +86 -0
  150. package/src/objects/CreateApiTokenInput.ts +22 -0
  151. package/src/objects/CreateApiTokenOutput.ts +41 -0
  152. package/src/objects/CreateInvoiceInput.ts +27 -0
  153. package/src/objects/CreateInvoiceOutput.ts +21 -0
  154. package/src/objects/CreateNodeWalletAddressInput.ts +15 -0
  155. package/src/objects/CreateNodeWalletAddressOutput.ts +27 -0
  156. package/src/objects/CurrencyAmount.ts +55 -0
  157. package/src/objects/CurrencyUnit.ts +25 -0
  158. package/src/objects/DeleteApiTokenInput.ts +13 -0
  159. package/src/objects/DeleteApiTokenOutput.ts +23 -0
  160. package/src/objects/Deposit.ts +144 -0
  161. package/src/objects/Entity.ts +868 -0
  162. package/src/objects/FeeEstimate.ts +39 -0
  163. package/src/objects/FundNodeInput.ts +16 -0
  164. package/src/objects/FundNodeOutput.ts +28 -0
  165. package/src/objects/GraphNode.ts +110 -0
  166. package/src/objects/Hop.ts +108 -0
  167. package/src/objects/HtlcAttemptFailureCode.ts +65 -0
  168. package/src/objects/IncomingPayment.ts +141 -0
  169. package/src/objects/IncomingPaymentAttempt.ts +96 -0
  170. package/src/objects/IncomingPaymentAttemptStatus.ts +20 -0
  171. package/src/objects/IncomingPaymentToAttemptsConnection.ts +39 -0
  172. package/src/objects/Invoice.ts +226 -0
  173. package/src/objects/InvoiceData.ts +185 -0
  174. package/src/objects/InvoiceType.ts +15 -0
  175. package/src/objects/LightningFeeEstimateForInvoiceInput.ts +28 -0
  176. package/src/objects/LightningFeeEstimateForNodeInput.ts +25 -0
  177. package/src/objects/LightningFeeEstimateOutput.ts +33 -0
  178. package/src/objects/LightningTransaction.ts +393 -0
  179. package/src/objects/LightsparkNode.ts +377 -0
  180. package/src/objects/LightsparkNodePurpose.ts +17 -0
  181. package/src/objects/LightsparkNodeStatus.ts +29 -0
  182. package/src/objects/LightsparkNodeToChannelsConnection.ts +50 -0
  183. package/src/objects/Node.ts +273 -0
  184. package/src/objects/NodeAddress.ts +29 -0
  185. package/src/objects/NodeAddressType.ts +18 -0
  186. package/src/objects/NodeToAddressesConnection.ts +39 -0
  187. package/src/objects/OnChainTransaction.ts +318 -0
  188. package/src/objects/OutgoingPayment.ts +319 -0
  189. package/src/objects/OutgoingPaymentAttempt.ts +164 -0
  190. package/src/objects/OutgoingPaymentAttemptStatus.ts +18 -0
  191. package/src/objects/OutgoingPaymentAttemptToHopsConnection.ts +37 -0
  192. package/src/objects/OutgoingPaymentToAttemptsConnection.ts +39 -0
  193. package/src/objects/PageInfo.ts +31 -0
  194. package/src/objects/PayInvoiceInput.ts +33 -0
  195. package/src/objects/PayInvoiceOutput.ts +22 -0
  196. package/src/objects/PaymentFailureReason.ts +29 -0
  197. package/src/objects/PaymentRequest.ts +231 -0
  198. package/src/objects/PaymentRequestData.ts +183 -0
  199. package/src/objects/PaymentRequestStatus.ts +15 -0
  200. package/src/objects/Permission.ts +39 -0
  201. package/src/objects/RequestWithdrawalInput.ts +35 -0
  202. package/src/objects/RequestWithdrawalOutput.ts +24 -0
  203. package/src/objects/RichText.ts +19 -0
  204. package/src/objects/RoutingTransaction.ts +150 -0
  205. package/src/objects/RoutingTransactionFailureReason.ts +17 -0
  206. package/src/objects/Secret.ts +23 -0
  207. package/src/objects/SendPaymentInput.ts +30 -0
  208. package/src/objects/SendPaymentOutput.ts +22 -0
  209. package/src/objects/Transaction.ts +609 -0
  210. package/src/objects/TransactionFailures.ts +23 -0
  211. package/src/objects/TransactionStatus.ts +23 -0
  212. package/src/objects/TransactionType.ts +31 -0
  213. package/src/objects/TransactionUpdate.ts +67 -0
  214. package/src/objects/WalletDashboard.ts +32 -0
  215. package/src/objects/WebhookEventType.ts +15 -0
  216. package/src/objects/Withdrawal.ts +144 -0
  217. package/src/objects/WithdrawalMode.ts +15 -0
  218. package/src/objects/WithdrawalRequest.ts +224 -0
  219. package/src/objects/WithdrawalRequestStatus.ts +17 -0
  220. package/src/objects/WithdrawalRequestToChannelClosingTransactionsConnection.ts +57 -0
  221. package/src/objects/WithdrawalRequestToChannelOpeningTransactionsConnection.ts +57 -0
  222. package/src/objects/index.ts +108 -0
  223. package/tsconfig.json +5 -0
@@ -0,0 +1,99 @@
1
+ import dayjs from "dayjs";
2
+ import utc from "dayjs/plugin/utc";
3
+ import { v4 as uuid } from "uuid";
4
+ import { INSTANCE_ID_KEY } from "../common/storage";
5
+ import StreamingDemoAccountCredentials from "./StreamingDemoCredentials";
6
+
7
+ const GRAPH_QL_ENDPOINT = "https://api.lightspark.com/graphql/frontend";
8
+
9
+ dayjs.extend(utc);
10
+
11
+ const getInstanceID = (): Promise<string> => {
12
+ return new Promise<string>((resolve) => {
13
+ chrome.storage.local.get(INSTANCE_ID_KEY, (result) => {
14
+ if (result.instanceID) {
15
+ resolve(result.instanceID);
16
+ } else {
17
+ const instanceID = uuid();
18
+ chrome.storage.local.set({ [INSTANCE_ID_KEY]: instanceID }, () => {
19
+ resolve(instanceID);
20
+ });
21
+ }
22
+ });
23
+ });
24
+ };
25
+
26
+ export const reserveStreamingDemoAccountCredentials =
27
+ async (): Promise<StreamingDemoAccountCredentials | null> => {
28
+ const response = await fetch(GRAPH_QL_ENDPOINT, {
29
+ method: "POST",
30
+ headers: {
31
+ "Content-Type": "application/json",
32
+ "X-Lightspark-Beta": "z2h0BBYxTA83cjW7fi8QwWtBPCzkQKiemcuhKY08LOo",
33
+ },
34
+ body: JSON.stringify({
35
+ query: `mutation DemoAccountReserve {
36
+ DEMO_reserve_streaming_sats_account(input: { extension_id: "${await getInstanceID()}" }) {
37
+ signing_private_key
38
+ sender_node_id
39
+ receiver_node_id
40
+ client_secret
41
+ api_token {
42
+ id
43
+ client_id
44
+ name
45
+ }
46
+ expires_at
47
+ allocation_time
48
+ }
49
+ }`,
50
+ operationName: "DemoAccountReserve",
51
+ }),
52
+ });
53
+ if (!response.ok) {
54
+ console.error("Failed to reserve demo account", response.statusText);
55
+ return null;
56
+ }
57
+ const responseJson = await response.json();
58
+ const data = responseJson.data.DEMO_reserve_streaming_sats_account;
59
+ if (!data) {
60
+ console.error(
61
+ "Failed to reserve demo account",
62
+ JSON.stringify(responseJson.errors)
63
+ );
64
+ return null;
65
+ }
66
+ return {
67
+ clientId: data.api_token.client_id,
68
+ clientSecret: data.client_secret,
69
+ viewerWalletId: data.sender_node_id,
70
+ creatorWalletId: data.receiver_node_id,
71
+ viewerSigningKey: data.signing_private_key,
72
+ apiTokenId: data.api_token.id,
73
+ expiresAt: dayjs.utc(data.expires_at).utc().valueOf(),
74
+ allocationTime: data.allocation_time,
75
+ };
76
+ };
77
+
78
+ export const unreserveStreamingDemoAccountCredentials = async (
79
+ credentials: StreamingDemoAccountCredentials
80
+ ): Promise<void> => {
81
+ await fetch(GRAPH_QL_ENDPOINT, {
82
+ method: "POST",
83
+ headers: {
84
+ "Content-Type": "application/json",
85
+ "X-Lightspark-Beta": "z2h0BBYxTA83cjW7fi8QwWtBPCzkQKiemcuhKY08LOo",
86
+ },
87
+ body: JSON.stringify({
88
+ query: `mutation DemoAccountUnreserve {
89
+ DEMO_unreserve_streaming_sats_account(input: {
90
+ extension_id: "${await getInstanceID()}"
91
+ api_token_id: "${credentials.apiTokenId}"
92
+ }) {
93
+ success
94
+ }
95
+ }`,
96
+ operationName: "DemoAccountUnreserve",
97
+ }),
98
+ });
99
+ };
@@ -0,0 +1,10 @@
1
+ export default interface StreamingDemoAccountCredentials {
2
+ clientId: string;
3
+ clientSecret: string;
4
+ viewerWalletId: string;
5
+ creatorWalletId: string;
6
+ viewerSigningKey: string;
7
+ apiTokenId: string;
8
+ expiresAt: number;
9
+ allocationTime: string;
10
+ }
@@ -0,0 +1,36 @@
1
+ import PlaybackRange from "./PlaybackRange";
2
+
3
+ export interface PaymentStrategy {
4
+ onPlayedRange(
5
+ previousRanges: PlaybackRange[],
6
+ newRanges: PlaybackRange[]
7
+ ): number;
8
+ }
9
+
10
+ export class LinearPaymentStrategy implements PaymentStrategy {
11
+ private readonly paymentPerChunkMsats: number;
12
+ private readonly chunkSizeSec: number;
13
+
14
+ constructor(paymentPerChunkMsats: number, chunkSizeSec: number) {
15
+ this.paymentPerChunkMsats = paymentPerChunkMsats;
16
+ this.chunkSizeSec = chunkSizeSec;
17
+ }
18
+
19
+ private numberOfChunksInRanges(ranges: PlaybackRange[]): number {
20
+ const totalDuration = ranges.reduce(
21
+ (acc, range) => acc + range.duration(),
22
+ 0
23
+ );
24
+ return Math.ceil(totalDuration / this.chunkSizeSec);
25
+ }
26
+
27
+ onPlayedRange(
28
+ previousRanges: PlaybackRange[],
29
+ newRanges: PlaybackRange[]
30
+ ): number {
31
+ const newChunks = this.numberOfChunksInRanges(newRanges);
32
+ const previousChunks = this.numberOfChunksInRanges(previousRanges);
33
+ const chunkDiff = newChunks - previousChunks;
34
+ return this.paymentPerChunkMsats * chunkDiff;
35
+ }
36
+ }
@@ -0,0 +1,31 @@
1
+ class PlaybackRange {
2
+ start: number;
3
+ end: number;
4
+
5
+ constructor(start: number, end: number) {
6
+ this.start = start;
7
+ this.end = end;
8
+ }
9
+
10
+ mergeWith(other: PlaybackRange) {
11
+ let start = this.start;
12
+ let end = this.end;
13
+ if (other.start < this.start) {
14
+ start = other.start;
15
+ }
16
+ if (other.end > this.end) {
17
+ end = other.end;
18
+ }
19
+ return new PlaybackRange(start, end);
20
+ }
21
+
22
+ isOverlapping(other: PlaybackRange) {
23
+ return this.start <= other.end && this.end >= other.start;
24
+ }
25
+
26
+ duration() {
27
+ return this.end - this.start;
28
+ }
29
+ }
30
+
31
+ export default PlaybackRange;
@@ -0,0 +1,33 @@
1
+ import { InvoiceType, LightsparkClient } from "@lightsparkdev/lightspark-sdk";
2
+ import autoBind from "auto-bind";
3
+
4
+ class StreamingInvoiceHolder {
5
+ constructor() {
6
+ autoBind(this);
7
+ }
8
+
9
+ public async createInvoice(
10
+ lightsparkClient: LightsparkClient,
11
+ creatorWalletId: string
12
+ ): Promise<String | undefined> {
13
+ const encodedInvoice = await lightsparkClient.createInvoice(
14
+ creatorWalletId,
15
+ 0,
16
+ "Streaming demo",
17
+ InvoiceType.AMP
18
+ );
19
+ await chrome.storage.local.set({ streamingInvoice: encodedInvoice });
20
+ return encodedInvoice;
21
+ }
22
+
23
+ public async getInvoiceData(): Promise<string | undefined> {
24
+ return (await chrome.storage.local.get("streamingInvoice"))
25
+ .streamingInvoice;
26
+ }
27
+
28
+ public async clearInvoice(): Promise<void> {
29
+ return await chrome.storage.local.remove("streamingInvoice");
30
+ }
31
+ }
32
+
33
+ export default StreamingInvoiceHolder;
@@ -0,0 +1,66 @@
1
+ import { LightsparkClient, Transaction } from "@lightsparkdev/lightspark-sdk";
2
+ import autoBind from "auto-bind";
3
+ import { Subscription } from "zen-observable-ts";
4
+ import { findActiveStreamingDemoTabs } from "../common/streamingTabs";
5
+
6
+ class TransactionObserver {
7
+ private isListening = false;
8
+ private subscription?: Subscription;
9
+ private readonly cachedTransactions = new Map<string, Transaction>();
10
+
11
+ constructor(private readonly lightsparkClient: LightsparkClient) {
12
+ autoBind(this);
13
+ }
14
+
15
+ public startListening(nodeId: string) {
16
+ console.log("Starting listening for transactions...");
17
+ if (this.isListening) {
18
+ return;
19
+ }
20
+
21
+ this.isListening = true;
22
+ this.subscription = this.lightsparkClient
23
+ .listenToTransactions([nodeId])
24
+ .subscribe({
25
+ next: (transaction) => {
26
+ if (transaction) {
27
+ this.broadcastTransactions([transaction]);
28
+ }
29
+ },
30
+ });
31
+ }
32
+
33
+ public clearCache() {
34
+ this.cachedTransactions.clear();
35
+ }
36
+
37
+ public stopListening() {
38
+ console.log("Stopping listening for transactions...");
39
+ if (!this.isListening || !this.subscription) {
40
+ return;
41
+ }
42
+
43
+ this.isListening = false;
44
+ this.subscription.unsubscribe();
45
+ this.subscription = undefined;
46
+ }
47
+
48
+ private async broadcastTransactions(transactions: Transaction[]) {
49
+ transactions.forEach((transaction) => {
50
+ this.cachedTransactions.set(transaction.id, transaction);
51
+ });
52
+ findActiveStreamingDemoTabs().then((tabs) => {
53
+ if (tabs.length === 0) return;
54
+ chrome.tabs.sendMessage(tabs[0].id!, {
55
+ id: "transactions_updated",
56
+ transactions,
57
+ });
58
+ });
59
+ chrome.runtime.sendMessage({
60
+ id: "transactions_updated",
61
+ transactions: Array.from(this.cachedTransactions.values()),
62
+ });
63
+ }
64
+ }
65
+
66
+ export default TransactionObserver;
@@ -0,0 +1,38 @@
1
+ import PlaybackRange from "./PlaybackRange";
2
+
3
+ class VideoPlaybackRanges {
4
+ private playedRanges: Array<PlaybackRange> = [];
5
+
6
+ addPlayedRange(start: number, end: number) {
7
+ if (start > end) return;
8
+ const newRange = new PlaybackRange(start, end);
9
+ if (!this.mergeOverlappingRangeIfApplicable(newRange)) {
10
+ this.playedRanges.push(newRange);
11
+ }
12
+ }
13
+
14
+ mergeOverlappingRangeIfApplicable(playbackRange: PlaybackRange): boolean {
15
+ for (let i = 0; i < this.playedRanges.length; i++) {
16
+ let range = this.playedRanges[i];
17
+ if (range.isOverlapping(playbackRange)) {
18
+ this.playedRanges[i] = range.mergeWith(playbackRange);
19
+ return true;
20
+ }
21
+ }
22
+ return false;
23
+ }
24
+
25
+ getPlayedRanges() {
26
+ return this.playedRanges;
27
+ }
28
+
29
+ getPlayedDuration() {
30
+ let duration = 0;
31
+ this.playedRanges.forEach((range) => {
32
+ duration += range.end - range.start;
33
+ });
34
+ return duration;
35
+ }
36
+ }
37
+
38
+ export default VideoPlaybackRanges;
@@ -0,0 +1,87 @@
1
+ import PlaybackRangesTracker from "./VideoPlaybackRanges";
2
+
3
+ class VideoProgressCache {
4
+ private videoProgressCache: { [videoID: string]: PlaybackRangesTracker };
5
+ private listeners: Array<(videoID: string) => void> = [];
6
+ private resolveWhenLoaded: () => void = () => {};
7
+ private whenLoadedPromise = new Promise<void>((resolve) => {
8
+ this.resolveWhenLoaded = resolve;
9
+ });
10
+
11
+ constructor() {
12
+ this.videoProgressCache = {};
13
+ this.readProgressFromStorage();
14
+ }
15
+
16
+ public async whenLoaded() {
17
+ return this.whenLoadedPromise;
18
+ }
19
+
20
+ public clear() {
21
+ this.videoProgressCache = {};
22
+ this.writeProgressToStorage();
23
+ }
24
+
25
+ addProgress(videoID: string, start: number, end: number) {
26
+ if (!this.videoProgressCache[videoID]) {
27
+ this.videoProgressCache[videoID] = new PlaybackRangesTracker();
28
+ }
29
+ this.videoProgressCache[videoID].addPlayedRange(start, end);
30
+ console.log(`Added progress for ${videoID}: ${start} - ${end}`);
31
+ console.log(
32
+ `Current ranges: ${JSON.stringify(
33
+ this.videoProgressCache[videoID].getPlayedRanges()
34
+ )}`
35
+ );
36
+ this.listeners.forEach((listener) => listener(videoID));
37
+ this.writeProgressToStorage();
38
+ }
39
+
40
+ listenForProgressChanges(listener: (videoID: string) => void) {
41
+ this.listeners.push(listener);
42
+ }
43
+
44
+ getPlayedDuration(videoID: string) {
45
+ if (!this.videoProgressCache[videoID]) {
46
+ return 0;
47
+ }
48
+ return this.videoProgressCache[videoID].getPlayedDuration();
49
+ }
50
+
51
+ getPlayedRanges(videoID: string) {
52
+ if (!this.videoProgressCache[videoID]) {
53
+ return [];
54
+ }
55
+ return this.videoProgressCache[videoID].getPlayedRanges();
56
+ }
57
+
58
+ readProgressFromStorage() {
59
+ chrome.storage.local.get(null, (result) => {
60
+ Object.keys(result).forEach((key) => {
61
+ if (key.startsWith("video_")) {
62
+ const videoID = key.replace("video_", "");
63
+ const videoRanges = result[key]["playedRanges"];
64
+ this.videoProgressCache[videoID] = new PlaybackRangesTracker();
65
+ videoRanges.forEach((range: any) => {
66
+ this.videoProgressCache[videoID].addPlayedRange(
67
+ range.start,
68
+ range.end
69
+ );
70
+ });
71
+ }
72
+ });
73
+ this.resolveWhenLoaded();
74
+ });
75
+ }
76
+
77
+ writeProgressToStorage() {
78
+ const newEntrys: any = {};
79
+ Object.keys(this.videoProgressCache).forEach((videoID) => {
80
+ const videoRanges = this.videoProgressCache[videoID];
81
+ newEntrys[`video_${videoID}`] = videoRanges;
82
+ });
83
+ chrome.storage.local.set(newEntrys);
84
+ }
85
+ }
86
+
87
+ export default VideoProgressCache;
@@ -0,0 +1,145 @@
1
+ import {
2
+ AccountTokenAuthProvider,
3
+ } from "@lightsparkdev/lightspark-sdk";
4
+ import AccountStorage from "../auth/AccountStorage";
5
+ import { unreserveStreamingDemoAccountCredentials } from "../auth/DemoAccountProvider";
6
+ import StreamingDemoAccountCredentials from "../auth/StreamingDemoCredentials";
7
+ import { clearStorageKeepingInstanceId } from "../common/storage";
8
+ import { findActiveStreamingDemoTabs } from "../common/streamingTabs";
9
+ import { getWalletClient } from "../lightsparkClientProvider";
10
+ import { onMessageReceived } from "./messageHandling";
11
+ import StreamingInvoiceHolder from "./StreamingInvoiceHolder";
12
+ import TransactionObserver from "./TransactionObserver";
13
+ import VideoProgressCache from "./VideoProgressCache";
14
+ import { StubAuthProvider } from "@lightsparkdev/core";
15
+
16
+ const progressCache = new VideoProgressCache();
17
+ const accountStorage = new AccountStorage();
18
+ const invoiceHolder = new StreamingInvoiceHolder();
19
+ const lightsparkClient = getWalletClient(accountStorage);
20
+ const transactionObserver = lightsparkClient.then(
21
+ (client) => new TransactionObserver(client)
22
+ );
23
+ let lastKnownStreamingTabId: number | undefined;
24
+
25
+ const setStreamingTabIdIfSender = (
26
+ message: { id: string },
27
+ sender: chrome.runtime.MessageSender
28
+ ) => {
29
+ if (
30
+ message.id === "video_details" &&
31
+ sender.url?.includes("demos/streaming") &&
32
+ sender.tab &&
33
+ sender.tab?.id
34
+ ) {
35
+ lastKnownStreamingTabId = sender.tab.id;
36
+ }
37
+ };
38
+
39
+ chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
40
+ Promise.all([lightsparkClient, transactionObserver]).then(
41
+ ([lightsparkClient, transactionObserver]) => {
42
+ setStreamingTabIdIfSender(message, sender);
43
+ onMessageReceived(
44
+ message,
45
+ lightsparkClient,
46
+ progressCache,
47
+ invoiceHolder,
48
+ accountStorage,
49
+ transactionObserver,
50
+ sendResponse
51
+ );
52
+ }
53
+ );
54
+ return true;
55
+ });
56
+
57
+ chrome.runtime.onMessageExternal.addListener(
58
+ (message, sender, sendResponse) => {
59
+ Promise.all([lightsparkClient, transactionObserver]).then(
60
+ ([lightsparkClient, transactionObserver]) => {
61
+ setStreamingTabIdIfSender(message, sender);
62
+ onMessageReceived(
63
+ message,
64
+ lightsparkClient,
65
+ progressCache,
66
+ invoiceHolder,
67
+ accountStorage,
68
+ transactionObserver,
69
+ sendResponse
70
+ );
71
+ }
72
+ );
73
+ return true;
74
+ }
75
+ );
76
+
77
+ const reloadOrOpenStreamingDemo = (openIfMissing: boolean = true) => {
78
+ findActiveStreamingDemoTabs().then(async (tabs) => {
79
+ console.log(`Found ${tabs.length} tabs to reload.`);
80
+ if (tabs.length > 0) {
81
+ chrome.tabs.update(tabs[0].id!, { active: true, highlighted: true });
82
+ chrome.tabs.reload(tabs[0].id!);
83
+ lastKnownStreamingTabId = tabs[0].id;
84
+ } else if (openIfMissing) {
85
+ // TODO: Replace with the final URL.
86
+ const newTab = await chrome.tabs.create({
87
+ url: "https://app.lightspark.com/demos/streaming",
88
+ active: true,
89
+ });
90
+ lastKnownStreamingTabId = newTab.id;
91
+ }
92
+ });
93
+ };
94
+
95
+ chrome.runtime.onInstalled.addListener((details) => {
96
+ if (details.reason === "install") {
97
+ reloadOrOpenStreamingDemo();
98
+ }
99
+ });
100
+
101
+ chrome.storage.local.onChanged.addListener((changes) => {
102
+ if (changes["credentials"]) {
103
+ console.log("Credentials changed, reloading tabs.");
104
+ lightsparkClient.then(async (lightsparkClient) => {
105
+ const credentials = changes["credentials"]
106
+ .newValue as StreamingDemoAccountCredentials;
107
+ if (credentials) {
108
+ lightsparkClient.setAuthProvider(
109
+ new AccountTokenAuthProvider(
110
+ credentials.clientId,
111
+ credentials.clientSecret
112
+ )
113
+ );
114
+ await lightsparkClient.loadNodeKey(
115
+ credentials.viewerWalletId,
116
+ credentials.viewerSigningKey
117
+ );
118
+ await invoiceHolder
119
+ .createInvoice(lightsparkClient, credentials.creatorWalletId)
120
+ .then((invoice) => {
121
+ console.log(`Created invoice: ${invoice}`);
122
+ });
123
+ } else {
124
+ await lightsparkClient.setAuthProvider(new StubAuthProvider());
125
+ await invoiceHolder.clearInvoice();
126
+ }
127
+ reloadOrOpenStreamingDemo(!!credentials);
128
+ });
129
+ return true;
130
+ }
131
+ return false;
132
+ });
133
+
134
+ chrome.tabs.onRemoved.addListener(async (tabId, _removeInfo) => {
135
+ if (tabId === lastKnownStreamingTabId) {
136
+ lastKnownStreamingTabId = undefined;
137
+ const account = await accountStorage.getAccountCredentials();
138
+ if (account) {
139
+ await unreserveStreamingDemoAccountCredentials(account);
140
+ }
141
+ await clearStorageKeepingInstanceId();
142
+ progressCache.clear();
143
+ (await transactionObserver).clearCache();
144
+ }
145
+ });