@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.
- package/.fossa.yml +6 -0
- package/.prettierrc +1 -0
- package/.turbo/turbo-build.log +19 -0
- package/.turbo/turbo-lint.log +3 -0
- package/CHANGELOG.md +49 -0
- package/LICENSE +201 -0
- package/README.md +137 -0
- package/dist/Withdrawal-17e1c8af.d.ts +1672 -0
- package/dist/Withdrawal-27a4d10d.d.ts +1672 -0
- package/dist/chunk-3VRI7CHE.js +5508 -0
- package/dist/chunk-AGEUDR2V.js +4498 -0
- package/dist/chunk-N27QHRE4.js +5508 -0
- package/dist/client-3bba3f64.d.ts +1302 -0
- package/dist/index.cjs +6633 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.js +1177 -0
- package/dist/objects/index.cjs +5347 -0
- package/dist/objects/index.d.ts +3 -0
- package/dist/objects/index.js +88 -0
- package/examples/node-scripts/authHelpers.ts +20 -0
- package/examples/node-scripts/createInvoice.ts +64 -0
- package/examples/node-scripts/example.ts +288 -0
- package/examples/node-scripts/getAccountDashboard.ts +24 -0
- package/examples/node-scripts/getNodeChannels.ts +34 -0
- package/examples/node-scripts/internalAuthHelpers.ts +26 -0
- package/examples/node-scripts/internal_example.ts +296 -0
- package/examples/node-scripts/package-lock.json +887 -0
- package/examples/node-scripts/package.json +22 -0
- package/examples/node-scripts/prettyPrintJsonForDocs.ts +62 -0
- package/examples/node-scripts/tsconfig.json +27 -0
- package/examples/oauth-example/README.md +19 -0
- package/examples/oauth-example/package-lock.json +16071 -0
- package/examples/oauth-example/package.json +50 -0
- package/examples/oauth-example/public/favicon.ico +0 -0
- package/examples/oauth-example/public/index.html +43 -0
- package/examples/oauth-example/public/logo192.png +0 -0
- package/examples/oauth-example/public/logo512.png +0 -0
- package/examples/oauth-example/public/manifest.json +25 -0
- package/examples/oauth-example/public/robots.txt +3 -0
- package/examples/oauth-example/src/App.css +7 -0
- package/examples/oauth-example/src/App.test.tsx +12 -0
- package/examples/oauth-example/src/App.tsx +16 -0
- package/examples/oauth-example/src/auth/AuthContext.ts +8 -0
- package/examples/oauth-example/src/auth/AuthProvider.tsx +44 -0
- package/examples/oauth-example/src/auth/RequireAuth.tsx +19 -0
- package/examples/oauth-example/src/auth/oauthProvider.ts +35 -0
- package/examples/oauth-example/src/components/Button.tsx +39 -0
- package/examples/oauth-example/src/components/CurrencyAmount.tsx +117 -0
- package/examples/oauth-example/src/components/Dashboard.tsx +158 -0
- package/examples/oauth-example/src/components/Table.tsx +22 -0
- package/examples/oauth-example/src/hooks/useAccountInfo.tsx +31 -0
- package/examples/oauth-example/src/icons/BitcoinB.tsx +20 -0
- package/examples/oauth-example/src/icons/Icon.tsx +121 -0
- package/examples/oauth-example/src/icons/Satoshi.tsx +28 -0
- package/examples/oauth-example/src/index.css +13 -0
- package/examples/oauth-example/src/index.tsx +23 -0
- package/examples/oauth-example/src/lightsparkclient/LightsparkClientContext.ts +10 -0
- package/examples/oauth-example/src/lightsparkclient/LightsparkClientProvider.tsx +53 -0
- package/examples/oauth-example/src/logo.svg +1 -0
- package/examples/oauth-example/src/pages/DashboardPage.tsx +71 -0
- package/examples/oauth-example/src/pages/LoginPage.tsx +63 -0
- package/examples/oauth-example/src/react-app-env.d.ts +1 -0
- package/examples/oauth-example/src/reportWebVitals.ts +15 -0
- package/examples/oauth-example/src/routes/index.tsx +15 -0
- package/examples/oauth-example/src/setupTests.ts +5 -0
- package/examples/oauth-example/src/utils/currency.ts +483 -0
- package/examples/oauth-example/tsconfig.json +20 -0
- package/examples/streaming-wallet-extension/.fossa.yml +6 -0
- package/examples/streaming-wallet-extension/README.md +17 -0
- package/examples/streaming-wallet-extension/craco.config.js +58 -0
- package/examples/streaming-wallet-extension/package-lock.json +18260 -0
- package/examples/streaming-wallet-extension/package.json +77 -0
- package/examples/streaming-wallet-extension/public/index.html +24 -0
- package/examples/streaming-wallet-extension/public/lightspark_full.png +0 -0
- package/examples/streaming-wallet-extension/public/lightspark_icon_circle.png +0 -0
- package/examples/streaming-wallet-extension/public/manifest.json +43 -0
- package/examples/streaming-wallet-extension/public/robots.txt +3 -0
- package/examples/streaming-wallet-extension/src/App.css +53 -0
- package/examples/streaming-wallet-extension/src/App.tsx +425 -0
- package/examples/streaming-wallet-extension/src/auth/AccountStorage.ts +28 -0
- package/examples/streaming-wallet-extension/src/auth/DemoAccountProvider.ts +99 -0
- package/examples/streaming-wallet-extension/src/auth/StreamingDemoCredentials.ts +10 -0
- package/examples/streaming-wallet-extension/src/background/PaymentStrategy.ts +36 -0
- package/examples/streaming-wallet-extension/src/background/PlaybackRange.ts +31 -0
- package/examples/streaming-wallet-extension/src/background/StreamingInvoiceHolder.ts +33 -0
- package/examples/streaming-wallet-extension/src/background/TransactionObserver.ts +66 -0
- package/examples/streaming-wallet-extension/src/background/VideoPlaybackRanges.ts +38 -0
- package/examples/streaming-wallet-extension/src/background/VideoProgressCache.ts +87 -0
- package/examples/streaming-wallet-extension/src/background/background.ts +145 -0
- package/examples/streaming-wallet-extension/src/background/messageHandling.ts +185 -0
- package/examples/streaming-wallet-extension/src/common/datetimes.ts +28 -0
- package/examples/streaming-wallet-extension/src/common/settings.ts +12 -0
- package/examples/streaming-wallet-extension/src/common/storage.ts +8 -0
- package/examples/streaming-wallet-extension/src/common/streamingTabs.ts +27 -0
- package/examples/streaming-wallet-extension/src/common/types.tsx +23 -0
- package/examples/streaming-wallet-extension/src/components/CirclePlusIcon.tsx +19 -0
- package/examples/streaming-wallet-extension/src/components/CurrencyAmount.tsx +110 -0
- package/examples/streaming-wallet-extension/src/components/CurrencyAmountRaw.tsx +195 -0
- package/examples/streaming-wallet-extension/src/components/LeftArrow.tsx +21 -0
- package/examples/streaming-wallet-extension/src/components/Loading.tsx +151 -0
- package/examples/streaming-wallet-extension/src/components/StreamingTransactionChip.tsx +95 -0
- package/examples/streaming-wallet-extension/src/components/TransactionRow.tsx +93 -0
- package/examples/streaming-wallet-extension/src/contentscript/content.ts +123 -0
- package/examples/streaming-wallet-extension/src/contentscript/lightsparkDemoDom.tsx +113 -0
- package/examples/streaming-wallet-extension/src/contentscript/videoElementParsers.ts +92 -0
- package/examples/streaming-wallet-extension/src/index.css +16 -0
- package/examples/streaming-wallet-extension/src/index.tsx +11 -0
- package/examples/streaming-wallet-extension/src/lightsparkClientProvider.tsx +26 -0
- package/examples/streaming-wallet-extension/src/react-app-env.d.ts +1 -0
- package/examples/streaming-wallet-extension/src/types/Messages.ts +17 -0
- package/examples/streaming-wallet-extension/tsconfig.json +20 -0
- package/package.json +87 -0
- package/src/auth/AccountTokenAuthProvider.ts +37 -0
- package/src/auth/index.ts +3 -0
- package/src/client.ts +759 -0
- package/src/graphql/BitcoinFeeEstimate.ts +13 -0
- package/src/graphql/CreateApiToken.ts +22 -0
- package/src/graphql/CreateInvoice.ts +18 -0
- package/src/graphql/CreateNodeWalletAddress.ts +13 -0
- package/src/graphql/CurrentAccount.ts +13 -0
- package/src/graphql/DecodeInvoice.ts +16 -0
- package/src/graphql/DeleteApiToken.ts +13 -0
- package/src/graphql/FundNode.ts +18 -0
- package/src/graphql/LightningFeeEstimateForInvoice.ts +21 -0
- package/src/graphql/LightningFeeEstimateForNode.ts +21 -0
- package/src/graphql/MultiNodeDashboard.ts +118 -0
- package/src/graphql/PayInvoice.ts +29 -0
- package/src/graphql/RecoverNodeSigningKey.ts +15 -0
- package/src/graphql/RequestWithdrawal.ts +25 -0
- package/src/graphql/SendPayment.ts +29 -0
- package/src/graphql/SingleNodeDashboard.ts +116 -0
- package/src/graphql/TransactionSubscription.ts +16 -0
- package/src/graphql/TransactionsForNode.ts +42 -0
- package/src/index.ts +5 -0
- package/src/objects/Account.ts +1222 -0
- package/src/objects/AccountToApiTokensConnection.ts +50 -0
- package/src/objects/AccountToChannelsConnection.ts +35 -0
- package/src/objects/AccountToNodesConnection.ts +62 -0
- package/src/objects/AccountToPaymentRequestsConnection.ts +50 -0
- package/src/objects/AccountToTransactionsConnection.ts +112 -0
- package/src/objects/ApiToken.ts +80 -0
- package/src/objects/BitcoinNetwork.ts +19 -0
- package/src/objects/BlockchainBalance.ts +102 -0
- package/src/objects/Channel.ts +283 -0
- package/src/objects/ChannelClosingTransaction.ts +150 -0
- package/src/objects/ChannelFees.ts +34 -0
- package/src/objects/ChannelOpeningTransaction.ts +150 -0
- package/src/objects/ChannelStatus.ts +25 -0
- package/src/objects/ChannelToTransactionsConnection.ts +86 -0
- package/src/objects/CreateApiTokenInput.ts +22 -0
- package/src/objects/CreateApiTokenOutput.ts +41 -0
- package/src/objects/CreateInvoiceInput.ts +27 -0
- package/src/objects/CreateInvoiceOutput.ts +21 -0
- package/src/objects/CreateNodeWalletAddressInput.ts +15 -0
- package/src/objects/CreateNodeWalletAddressOutput.ts +27 -0
- package/src/objects/CurrencyAmount.ts +55 -0
- package/src/objects/CurrencyUnit.ts +25 -0
- package/src/objects/DeleteApiTokenInput.ts +13 -0
- package/src/objects/DeleteApiTokenOutput.ts +23 -0
- package/src/objects/Deposit.ts +144 -0
- package/src/objects/Entity.ts +868 -0
- package/src/objects/FeeEstimate.ts +39 -0
- package/src/objects/FundNodeInput.ts +16 -0
- package/src/objects/FundNodeOutput.ts +28 -0
- package/src/objects/GraphNode.ts +110 -0
- package/src/objects/Hop.ts +108 -0
- package/src/objects/HtlcAttemptFailureCode.ts +65 -0
- package/src/objects/IncomingPayment.ts +141 -0
- package/src/objects/IncomingPaymentAttempt.ts +96 -0
- package/src/objects/IncomingPaymentAttemptStatus.ts +20 -0
- package/src/objects/IncomingPaymentToAttemptsConnection.ts +39 -0
- package/src/objects/Invoice.ts +226 -0
- package/src/objects/InvoiceData.ts +185 -0
- package/src/objects/InvoiceType.ts +15 -0
- package/src/objects/LightningFeeEstimateForInvoiceInput.ts +28 -0
- package/src/objects/LightningFeeEstimateForNodeInput.ts +25 -0
- package/src/objects/LightningFeeEstimateOutput.ts +33 -0
- package/src/objects/LightningTransaction.ts +393 -0
- package/src/objects/LightsparkNode.ts +377 -0
- package/src/objects/LightsparkNodePurpose.ts +17 -0
- package/src/objects/LightsparkNodeStatus.ts +29 -0
- package/src/objects/LightsparkNodeToChannelsConnection.ts +50 -0
- package/src/objects/Node.ts +273 -0
- package/src/objects/NodeAddress.ts +29 -0
- package/src/objects/NodeAddressType.ts +18 -0
- package/src/objects/NodeToAddressesConnection.ts +39 -0
- package/src/objects/OnChainTransaction.ts +318 -0
- package/src/objects/OutgoingPayment.ts +319 -0
- package/src/objects/OutgoingPaymentAttempt.ts +164 -0
- package/src/objects/OutgoingPaymentAttemptStatus.ts +18 -0
- package/src/objects/OutgoingPaymentAttemptToHopsConnection.ts +37 -0
- package/src/objects/OutgoingPaymentToAttemptsConnection.ts +39 -0
- package/src/objects/PageInfo.ts +31 -0
- package/src/objects/PayInvoiceInput.ts +33 -0
- package/src/objects/PayInvoiceOutput.ts +22 -0
- package/src/objects/PaymentFailureReason.ts +29 -0
- package/src/objects/PaymentRequest.ts +231 -0
- package/src/objects/PaymentRequestData.ts +183 -0
- package/src/objects/PaymentRequestStatus.ts +15 -0
- package/src/objects/Permission.ts +39 -0
- package/src/objects/RequestWithdrawalInput.ts +35 -0
- package/src/objects/RequestWithdrawalOutput.ts +24 -0
- package/src/objects/RichText.ts +19 -0
- package/src/objects/RoutingTransaction.ts +150 -0
- package/src/objects/RoutingTransactionFailureReason.ts +17 -0
- package/src/objects/Secret.ts +23 -0
- package/src/objects/SendPaymentInput.ts +30 -0
- package/src/objects/SendPaymentOutput.ts +22 -0
- package/src/objects/Transaction.ts +609 -0
- package/src/objects/TransactionFailures.ts +23 -0
- package/src/objects/TransactionStatus.ts +23 -0
- package/src/objects/TransactionType.ts +31 -0
- package/src/objects/TransactionUpdate.ts +67 -0
- package/src/objects/WalletDashboard.ts +32 -0
- package/src/objects/WebhookEventType.ts +15 -0
- package/src/objects/Withdrawal.ts +144 -0
- package/src/objects/WithdrawalMode.ts +15 -0
- package/src/objects/WithdrawalRequest.ts +224 -0
- package/src/objects/WithdrawalRequestStatus.ts +17 -0
- package/src/objects/WithdrawalRequestToChannelClosingTransactionsConnection.ts +57 -0
- package/src/objects/WithdrawalRequestToChannelOpeningTransactionsConnection.ts +57 -0
- package/src/objects/index.ts +108 -0
- package/tsconfig.json +5 -0
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import {
|
|
2
|
+
BitcoinNetwork,
|
|
3
|
+
CurrencyUnit,
|
|
4
|
+
LightsparkClient,
|
|
5
|
+
} from "@lightsparkdev/lightspark-sdk";
|
|
6
|
+
import AccountStorage from "../auth/AccountStorage";
|
|
7
|
+
import { VideoPlaybackUpdateMessage } from "../types/Messages";
|
|
8
|
+
import { LinearPaymentStrategy } from "./PaymentStrategy";
|
|
9
|
+
import StreamingInvoiceHolder from "./StreamingInvoiceHolder";
|
|
10
|
+
import TransactionObserver from "./TransactionObserver";
|
|
11
|
+
import VideoProgressCache from "./VideoProgressCache";
|
|
12
|
+
|
|
13
|
+
const paymentStrategy = new LinearPaymentStrategy(10_000, 1);
|
|
14
|
+
|
|
15
|
+
const playbackMessageReceived = async (
|
|
16
|
+
message: VideoPlaybackUpdateMessage,
|
|
17
|
+
lightsparkClient: LightsparkClient,
|
|
18
|
+
viewerNodeId: string | undefined,
|
|
19
|
+
progressCache: VideoProgressCache,
|
|
20
|
+
invoiceHolder: StreamingInvoiceHolder,
|
|
21
|
+
sendResponse: (response?: any) => void
|
|
22
|
+
) => {
|
|
23
|
+
const previousRanges = progressCache.getPlayedRanges(message.videoID).slice();
|
|
24
|
+
progressCache.addProgress(
|
|
25
|
+
message.videoID,
|
|
26
|
+
message.prevProgress || 0,
|
|
27
|
+
message.progress
|
|
28
|
+
);
|
|
29
|
+
// Only send payments for the demo streaming video for now:
|
|
30
|
+
if (message.videoID !== "ls_demo") {
|
|
31
|
+
sendResponse({ amountToPay: 0 });
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
const amountToPay = paymentStrategy.onPlayedRange(
|
|
35
|
+
previousRanges,
|
|
36
|
+
progressCache.getPlayedRanges(message.videoID)
|
|
37
|
+
);
|
|
38
|
+
const invoiceToPay = await invoiceHolder.getInvoiceData();
|
|
39
|
+
if (amountToPay > 0) {
|
|
40
|
+
console.log(`Paying: ${amountToPay / 1000} sats`);
|
|
41
|
+
if (!invoiceToPay || !viewerNodeId) {
|
|
42
|
+
console.error("No invoice to pay while streaming");
|
|
43
|
+
} else {
|
|
44
|
+
await lightsparkClient.payInvoice(
|
|
45
|
+
viewerNodeId,
|
|
46
|
+
invoiceToPay,
|
|
47
|
+
Math.ceil(amountToPay * 0.0016 + 5),
|
|
48
|
+
60,
|
|
49
|
+
amountToPay
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
sendResponse({ amountToPay });
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
const getWalletStatus = async (lightsparkClient: LightsparkClient) => {
|
|
57
|
+
const isAuthorized = await lightsparkClient.isAuthorized();
|
|
58
|
+
if (!isAuthorized) {
|
|
59
|
+
return "no_wallet";
|
|
60
|
+
}
|
|
61
|
+
return "funded";
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
let pendingPause: NodeJS.Timeout | undefined;
|
|
65
|
+
|
|
66
|
+
export const onMessageReceived = (
|
|
67
|
+
message: any,
|
|
68
|
+
lightsparkClient: LightsparkClient,
|
|
69
|
+
progressCache: VideoProgressCache,
|
|
70
|
+
invoiceHolder: StreamingInvoiceHolder,
|
|
71
|
+
accountStorage: AccountStorage,
|
|
72
|
+
transactionObserver: TransactionObserver,
|
|
73
|
+
sendResponse: (response: any) => void
|
|
74
|
+
) => {
|
|
75
|
+
switch (message.id) {
|
|
76
|
+
case "video_play":
|
|
77
|
+
accountStorage.getAccountCredentials().then((account) => {
|
|
78
|
+
transactionObserver.startListening(account!.viewerWalletId);
|
|
79
|
+
if (pendingPause) {
|
|
80
|
+
clearTimeout(pendingPause);
|
|
81
|
+
pendingPause = undefined;
|
|
82
|
+
}
|
|
83
|
+
sendResponse({ status: "ok" });
|
|
84
|
+
});
|
|
85
|
+
break;
|
|
86
|
+
case "video_pause":
|
|
87
|
+
pendingPause = setTimeout(() => {
|
|
88
|
+
transactionObserver.stopListening();
|
|
89
|
+
pendingPause = undefined;
|
|
90
|
+
}, 10000);
|
|
91
|
+
sendResponse({ status: "ok" });
|
|
92
|
+
break;
|
|
93
|
+
case "ping":
|
|
94
|
+
sendResponse("pong");
|
|
95
|
+
break;
|
|
96
|
+
case "get_version":
|
|
97
|
+
sendResponse({ version: chrome.runtime.getManifest().version });
|
|
98
|
+
break;
|
|
99
|
+
case "video_progress":
|
|
100
|
+
accountStorage.getAccountCredentials().then((account) => {
|
|
101
|
+
playbackMessageReceived(
|
|
102
|
+
message,
|
|
103
|
+
lightsparkClient,
|
|
104
|
+
account?.viewerWalletId,
|
|
105
|
+
progressCache,
|
|
106
|
+
invoiceHolder,
|
|
107
|
+
sendResponse
|
|
108
|
+
);
|
|
109
|
+
});
|
|
110
|
+
break;
|
|
111
|
+
case "get_wallet_status":
|
|
112
|
+
// TODO: Send messages when the status changes.
|
|
113
|
+
getWalletStatus(lightsparkClient).then((status) => {
|
|
114
|
+
sendResponse({ status });
|
|
115
|
+
});
|
|
116
|
+
break;
|
|
117
|
+
case "get_wallet_transactions":
|
|
118
|
+
accountStorage.getAccountCredentials().then((account) => {
|
|
119
|
+
if (!account) {
|
|
120
|
+
sendResponse({ transactions: [] });
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
lightsparkClient
|
|
125
|
+
.getRecentTransactions(
|
|
126
|
+
account.viewerWalletId,
|
|
127
|
+
20,
|
|
128
|
+
BitcoinNetwork.REGTEST,
|
|
129
|
+
account.allocationTime
|
|
130
|
+
)
|
|
131
|
+
.then((transactions) => {
|
|
132
|
+
sendResponse({ transactions });
|
|
133
|
+
});
|
|
134
|
+
});
|
|
135
|
+
break;
|
|
136
|
+
case "get_streaming_wallet_balances":
|
|
137
|
+
// Hack for testing. Remove this line when releasing:
|
|
138
|
+
progressCache.clear();
|
|
139
|
+
lightsparkClient
|
|
140
|
+
.getAccountDashboard(undefined, BitcoinNetwork.REGTEST)
|
|
141
|
+
.then(async (dashboard) => {
|
|
142
|
+
const zeroSats = { unit: CurrencyUnit.SATOSHI, value: 0 };
|
|
143
|
+
const account = await accountStorage.getAccountCredentials();
|
|
144
|
+
if (!account) {
|
|
145
|
+
sendResponse({
|
|
146
|
+
balances: { viewerBalance: zeroSats, creatorBalance: zeroSats },
|
|
147
|
+
});
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
const viewerNode = dashboard.nodes?.find((node) =>
|
|
151
|
+
node.id.includes(account.viewerWalletId)
|
|
152
|
+
);
|
|
153
|
+
const creatorNode = dashboard.nodes?.find((node) =>
|
|
154
|
+
node.id.includes(account.creatorWalletId)
|
|
155
|
+
);
|
|
156
|
+
const balances = {
|
|
157
|
+
viewerBalance: viewerNode?.localBalance || zeroSats,
|
|
158
|
+
creatorBalance: creatorNode?.localBalance || zeroSats,
|
|
159
|
+
};
|
|
160
|
+
sendResponse({ balances });
|
|
161
|
+
});
|
|
162
|
+
break;
|
|
163
|
+
case "open_and_create_wallet":
|
|
164
|
+
chrome.windows.getCurrent().then((activeWindow) => {
|
|
165
|
+
chrome.windows.create(
|
|
166
|
+
{
|
|
167
|
+
url: "index.html",
|
|
168
|
+
type: "popup",
|
|
169
|
+
width: 300,
|
|
170
|
+
height: 408,
|
|
171
|
+
left: Math.round(
|
|
172
|
+
(activeWindow.left ?? 0) + (activeWindow.width ?? 0) - 480
|
|
173
|
+
),
|
|
174
|
+
top: Math.round((activeWindow.top ?? 0) + 90),
|
|
175
|
+
},
|
|
176
|
+
() => console.log("opened popup")
|
|
177
|
+
);
|
|
178
|
+
});
|
|
179
|
+
sendResponse({ status: "ok" });
|
|
180
|
+
break;
|
|
181
|
+
default:
|
|
182
|
+
console.log(`Unknown message received: ${JSON.stringify(message)}`);
|
|
183
|
+
sendResponse({ status: "unknown" });
|
|
184
|
+
}
|
|
185
|
+
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import day from "dayjs";
|
|
2
|
+
import utc from "dayjs/plugin/utc";
|
|
3
|
+
import { Maybe } from "./types";
|
|
4
|
+
|
|
5
|
+
const NOT_APPLICABLE = "-";
|
|
6
|
+
|
|
7
|
+
day.extend(utc);
|
|
8
|
+
|
|
9
|
+
export const formatDateTime = (
|
|
10
|
+
datetime: string,
|
|
11
|
+
format: string,
|
|
12
|
+
toUserTime: boolean = true
|
|
13
|
+
): string => {
|
|
14
|
+
let time_val = day(datetime).utc();
|
|
15
|
+
if (toUserTime) {
|
|
16
|
+
time_val = day(time_val).local();
|
|
17
|
+
}
|
|
18
|
+
return time_val.format(format);
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export const getFormattedDateTimeOrDefault = (
|
|
22
|
+
datetime: Maybe<string>,
|
|
23
|
+
format: string
|
|
24
|
+
): string => {
|
|
25
|
+
return datetime === undefined || datetime === null || datetime === ""
|
|
26
|
+
? NOT_APPLICABLE
|
|
27
|
+
: formatDateTime(datetime, format);
|
|
28
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Enable YouTube and Twitch streaming tracking.
|
|
3
|
+
*
|
|
4
|
+
* If you enable this, you will need to add the following to your manifest.json in content_scripts -> matches:
|
|
5
|
+
* [
|
|
6
|
+
* "https://youtube.com/*",
|
|
7
|
+
* "https://www.youtube.com/*",
|
|
8
|
+
* "https://www.twitch.tv/*",
|
|
9
|
+
* "https://twitch.tv/*",
|
|
10
|
+
* ]
|
|
11
|
+
*/
|
|
12
|
+
export const ENABLE_YOUTUBE_AND_TWITCH = false;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export const INSTANCE_ID_KEY = "instanceID";
|
|
2
|
+
|
|
3
|
+
export const clearStorageKeepingInstanceId = async () => {
|
|
4
|
+
const instanceId = (await chrome.storage.local.get(INSTANCE_ID_KEY))
|
|
5
|
+
?.instanceID;
|
|
6
|
+
await chrome.storage.local.clear();
|
|
7
|
+
await chrome.storage.local.set({ [INSTANCE_ID_KEY]: instanceId });
|
|
8
|
+
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
const URLS = [
|
|
2
|
+
"https://localhost:3000/demos/streaming",
|
|
3
|
+
"http://192.168.86.248:3000/demos/streaming",
|
|
4
|
+
"https://dev.dev.sparkinfra.net/demos/streaming",
|
|
5
|
+
"https://app.lightspark.com/demos/streaming",
|
|
6
|
+
];
|
|
7
|
+
|
|
8
|
+
export const findActiveStreamingDemoTabs = () => {
|
|
9
|
+
const allAndActive = Promise.all([
|
|
10
|
+
new Promise<chrome.tabs.Tab[]>((resolve) => {
|
|
11
|
+
chrome.tabs.query({ url: URLS }, (tabs) => resolve(tabs));
|
|
12
|
+
}),
|
|
13
|
+
new Promise<chrome.tabs.Tab[]>((resolve) => {
|
|
14
|
+
chrome.tabs.query(
|
|
15
|
+
{ url: URLS, active: true, lastFocusedWindow: true },
|
|
16
|
+
(tabs) => resolve(tabs)
|
|
17
|
+
);
|
|
18
|
+
}),
|
|
19
|
+
]);
|
|
20
|
+
return allAndActive.then(([all, active]) => {
|
|
21
|
+
if (active.length > 0) {
|
|
22
|
+
return active;
|
|
23
|
+
}
|
|
24
|
+
// Reverse the order so that the most recently opened tab is returned.
|
|
25
|
+
return all.reverse();
|
|
26
|
+
});
|
|
27
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// Copyright ©, 2022, Lightspark Group, Inc. - All Rights Reserved
|
|
2
|
+
|
|
3
|
+
export type Maybe<T> = T | null | undefined;
|
|
4
|
+
|
|
5
|
+
export type ExpandRecursively<T> = T extends object
|
|
6
|
+
? T extends infer O
|
|
7
|
+
? { [K in keyof O]: ExpandRecursively<O[K]> } // eslint-disable-line @typescript-eslint/no-unused-vars
|
|
8
|
+
: never
|
|
9
|
+
: T;
|
|
10
|
+
|
|
11
|
+
export type ById<T> = {
|
|
12
|
+
[id: string]: T;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export type OmitTypename<T> = Omit<T, "__typename">;
|
|
16
|
+
|
|
17
|
+
export const isType =
|
|
18
|
+
<T extends string>(typename: T) =>
|
|
19
|
+
<N extends { __typename: string }>(
|
|
20
|
+
node: N | undefined | null
|
|
21
|
+
): node is Extract<N, { __typename: T }> => {
|
|
22
|
+
return node?.__typename === typename;
|
|
23
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
// Copyright ©, 2022, Lightspark Group, Inc. - All Rights Reserved
|
|
2
|
+
|
|
3
|
+
const CirclePlusIcon = () => (
|
|
4
|
+
<svg
|
|
5
|
+
width="12"
|
|
6
|
+
height="13"
|
|
7
|
+
viewBox="0 0 12 13"
|
|
8
|
+
fill="none"
|
|
9
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
10
|
+
>
|
|
11
|
+
<path
|
|
12
|
+
d="M6 3.75V9.25M3.25 6.5H8.75M11.5 6.5C11.5 9.53757 9.03757 12 6 12C2.96243 12 0.5 9.53757 0.5 6.5C0.5 3.46243 2.96243 1 6 1C9.03757 1 11.5 3.46243 11.5 6.5Z"
|
|
13
|
+
stroke="white"
|
|
14
|
+
stroke-linecap="round"
|
|
15
|
+
/>
|
|
16
|
+
</svg>
|
|
17
|
+
);
|
|
18
|
+
|
|
19
|
+
export default CirclePlusIcon;
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
// Copyright ©, 2022, Lightspark Group, Inc. - All Rights Reserved
|
|
2
|
+
import {
|
|
3
|
+
CurrencyAmount as CurrencyAmountType,
|
|
4
|
+
CurrencyUnit,
|
|
5
|
+
} from "@lightsparkdev/lightspark-sdk";
|
|
6
|
+
import { Maybe } from "../common/types";
|
|
7
|
+
import CurrencyAmountRaw from "./CurrencyAmountRaw";
|
|
8
|
+
|
|
9
|
+
type Props = {
|
|
10
|
+
amount?: CurrencyAmountType | null;
|
|
11
|
+
displayUnit?: CurrencyUnit;
|
|
12
|
+
shortNumber?: boolean;
|
|
13
|
+
shortUnit?: boolean;
|
|
14
|
+
symbol?: boolean;
|
|
15
|
+
useLocaleString?: boolean;
|
|
16
|
+
maximumSignificantDigits?: number;
|
|
17
|
+
maximumFractionDigits?: number;
|
|
18
|
+
minimumFractionDigits?: number;
|
|
19
|
+
dash?: boolean;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const CurrencyAmount = (props: Props) => {
|
|
23
|
+
if (!props.amount) {
|
|
24
|
+
return props.dash ? <>-</> : null;
|
|
25
|
+
}
|
|
26
|
+
const amount = convert(props.amount, props.displayUnit);
|
|
27
|
+
return (
|
|
28
|
+
<CurrencyAmountRaw
|
|
29
|
+
value={amount.preferredCurrencyValueApprox}
|
|
30
|
+
unit={amount.preferredCurrencyUnit}
|
|
31
|
+
shortNumber={props.shortNumber}
|
|
32
|
+
shortUnit={props.shortUnit}
|
|
33
|
+
symbol={props.symbol}
|
|
34
|
+
useLocaleString={props.useLocaleString}
|
|
35
|
+
maximumSignificantDigits={props.maximumSignificantDigits}
|
|
36
|
+
maximumFractionDigits={props.maximumFractionDigits}
|
|
37
|
+
minimumFractionDigits={props.minimumFractionDigits}
|
|
38
|
+
/>
|
|
39
|
+
);
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
// TODO(Jeremy): consider moving this to fetch the actual exchange rate.
|
|
43
|
+
const SATS_TO_USD = 0.0268;
|
|
44
|
+
const btc_conversions: Map<CurrencyUnit, Map<CurrencyUnit, number>> = new Map([
|
|
45
|
+
[
|
|
46
|
+
CurrencyUnit.BITCOIN,
|
|
47
|
+
new Map([
|
|
48
|
+
[CurrencyUnit.BITCOIN, 1],
|
|
49
|
+
[CurrencyUnit.SATOSHI, 1e8],
|
|
50
|
+
[CurrencyUnit.MILLISATOSHI, 1e11],
|
|
51
|
+
]),
|
|
52
|
+
],
|
|
53
|
+
[
|
|
54
|
+
CurrencyUnit.SATOSHI,
|
|
55
|
+
new Map([
|
|
56
|
+
[CurrencyUnit.BITCOIN, 1e-8],
|
|
57
|
+
[CurrencyUnit.SATOSHI, 1],
|
|
58
|
+
[CurrencyUnit.MILLISATOSHI, 1000],
|
|
59
|
+
]),
|
|
60
|
+
],
|
|
61
|
+
[
|
|
62
|
+
CurrencyUnit.MILLISATOSHI,
|
|
63
|
+
new Map([
|
|
64
|
+
[CurrencyUnit.BITCOIN, 1e-11],
|
|
65
|
+
[CurrencyUnit.SATOSHI, 0.001],
|
|
66
|
+
[CurrencyUnit.MILLISATOSHI, 1],
|
|
67
|
+
]),
|
|
68
|
+
],
|
|
69
|
+
[
|
|
70
|
+
CurrencyUnit.USD,
|
|
71
|
+
new Map([
|
|
72
|
+
[CurrencyUnit.USD, 1],
|
|
73
|
+
[CurrencyUnit.SATOSHI, SATS_TO_USD],
|
|
74
|
+
[CurrencyUnit.BITCOIN, SATS_TO_USD * 1e8],
|
|
75
|
+
[CurrencyUnit.MILLISATOSHI, SATS_TO_USD / 1000],
|
|
76
|
+
]),
|
|
77
|
+
],
|
|
78
|
+
]);
|
|
79
|
+
|
|
80
|
+
const convert = (
|
|
81
|
+
amount: CurrencyAmountType,
|
|
82
|
+
unit: Maybe<CurrencyUnit>
|
|
83
|
+
): CurrencyAmountType => {
|
|
84
|
+
if (unit === null || unit === undefined || unit === amount.originalUnit)
|
|
85
|
+
return amount;
|
|
86
|
+
const multiplier = btc_conversions.get(amount.originalUnit)?.get(unit);
|
|
87
|
+
if (!multiplier) {
|
|
88
|
+
throw new ConversionError(
|
|
89
|
+
`Unable to convert from ${amount.originalUnit} to ${unit}`
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return {
|
|
94
|
+
originalUnit: amount.originalUnit,
|
|
95
|
+
originalValue: amount.originalValue,
|
|
96
|
+
preferredCurrencyUnit: unit,
|
|
97
|
+
preferredCurrencyValueApprox: amount.originalValue * multiplier,
|
|
98
|
+
preferredCurrencyValueRounded: amount.originalValue * multiplier,
|
|
99
|
+
};
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
export class ConversionError {
|
|
103
|
+
message: string;
|
|
104
|
+
|
|
105
|
+
constructor(message: string) {
|
|
106
|
+
this.message = message;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export default CurrencyAmount;
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
// Copyright ©, 2022, Lightspark Group, Inc. - All Rights Reserved
|
|
2
|
+
import styled from "@emotion/styled/macro";
|
|
3
|
+
import { CurrencyUnit } from "@lightsparkdev/lightspark-sdk";
|
|
4
|
+
import type { Maybe } from "../common/types";
|
|
5
|
+
|
|
6
|
+
type Props = {
|
|
7
|
+
value: Maybe<number>;
|
|
8
|
+
unit: Maybe<CurrencyUnit>;
|
|
9
|
+
shortUnit?: boolean;
|
|
10
|
+
symbol?: boolean;
|
|
11
|
+
shortNumber?: boolean;
|
|
12
|
+
useLocaleString?: boolean;
|
|
13
|
+
maximumSignificantDigits?: number;
|
|
14
|
+
maximumFractionDigits?: number;
|
|
15
|
+
minimumFractionDigits?: number;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const CurrencyAmountRaw = (props: Props) => {
|
|
19
|
+
const symbol = () => {
|
|
20
|
+
switch (props.unit) {
|
|
21
|
+
case CurrencyUnit.SATOSHI:
|
|
22
|
+
return <Satoshi />;
|
|
23
|
+
case CurrencyUnit.USD:
|
|
24
|
+
return "$";
|
|
25
|
+
}
|
|
26
|
+
return "";
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const text = getAsText(props);
|
|
30
|
+
return (
|
|
31
|
+
<Amount>
|
|
32
|
+
{symbol()}
|
|
33
|
+
{text}
|
|
34
|
+
</Amount>
|
|
35
|
+
);
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export const getAsText = (props: Props): string => {
|
|
39
|
+
const {
|
|
40
|
+
value,
|
|
41
|
+
unit,
|
|
42
|
+
shortUnit,
|
|
43
|
+
symbol,
|
|
44
|
+
shortNumber,
|
|
45
|
+
useLocaleString,
|
|
46
|
+
maximumSignificantDigits,
|
|
47
|
+
maximumFractionDigits,
|
|
48
|
+
minimumFractionDigits,
|
|
49
|
+
} = props;
|
|
50
|
+
|
|
51
|
+
if (value === undefined || value === null) {
|
|
52
|
+
return "ERROR";
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
let amountValue = value;
|
|
56
|
+
/* Currencies should always be represented in the smallest unit, e.g. cents for USD: */
|
|
57
|
+
if (unit === CurrencyUnit.USD) {
|
|
58
|
+
amountValue = value / 100;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
let number = amountValue.toString();
|
|
62
|
+
if (shortNumber) {
|
|
63
|
+
const abs_val = Math.abs(amountValue);
|
|
64
|
+
if (abs_val >= 1_000_000_000) {
|
|
65
|
+
const newValue = amountValue / 1_000_000_000;
|
|
66
|
+
number = newValue.toFixed(newValue >= 100 ? 0 : 1) + "B";
|
|
67
|
+
} else if (abs_val >= 1_000_000) {
|
|
68
|
+
const newValue = amountValue / 1_000_000;
|
|
69
|
+
number = newValue.toFixed(newValue >= 100 ? 0 : 1) + "M";
|
|
70
|
+
} else if (abs_val >= 1_000) {
|
|
71
|
+
const newValue = amountValue / 1_000;
|
|
72
|
+
number = (amountValue / 1_000).toFixed(newValue >= 100 ? 0 : 1) + "K";
|
|
73
|
+
} else {
|
|
74
|
+
number = amountValue.toFixed(3);
|
|
75
|
+
}
|
|
76
|
+
} else if (useLocaleString) {
|
|
77
|
+
const options: Intl.NumberFormatOptions = {};
|
|
78
|
+
if (maximumSignificantDigits !== undefined) {
|
|
79
|
+
options.maximumSignificantDigits = maximumSignificantDigits;
|
|
80
|
+
}
|
|
81
|
+
if (maximumFractionDigits !== undefined) {
|
|
82
|
+
options.maximumFractionDigits = maximumFractionDigits;
|
|
83
|
+
}
|
|
84
|
+
if (minimumFractionDigits !== undefined) {
|
|
85
|
+
options.minimumFractionDigits = minimumFractionDigits;
|
|
86
|
+
}
|
|
87
|
+
number = Number(number).toLocaleString(undefined, options);
|
|
88
|
+
}
|
|
89
|
+
if (!unit || symbol) {
|
|
90
|
+
return number;
|
|
91
|
+
}
|
|
92
|
+
if (shortUnit) {
|
|
93
|
+
return number + " " + shorttext(unit);
|
|
94
|
+
}
|
|
95
|
+
const isPlural = amountValue > 1;
|
|
96
|
+
const unitText = isPlural ? plural(unit) : singular(unit);
|
|
97
|
+
return number + " " + unitText;
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
const singular = (unit: CurrencyUnit) => {
|
|
101
|
+
switch (unit) {
|
|
102
|
+
case CurrencyUnit.BITCOIN:
|
|
103
|
+
return "Bitcoin";
|
|
104
|
+
case CurrencyUnit.MILLIBITCOIN:
|
|
105
|
+
return "Millibitcoin";
|
|
106
|
+
case CurrencyUnit.MICROBITCOIN:
|
|
107
|
+
return "Microbitcoin";
|
|
108
|
+
case CurrencyUnit.NANOBITCOIN:
|
|
109
|
+
return "Nanobitcoin";
|
|
110
|
+
case CurrencyUnit.SATOSHI:
|
|
111
|
+
return "Satoshi";
|
|
112
|
+
case CurrencyUnit.MILLISATOSHI:
|
|
113
|
+
return "Millisatoshi";
|
|
114
|
+
}
|
|
115
|
+
return unit;
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
const plural = (unit: CurrencyUnit) => {
|
|
119
|
+
switch (unit) {
|
|
120
|
+
case CurrencyUnit.BITCOIN:
|
|
121
|
+
return "Bitcoins";
|
|
122
|
+
case CurrencyUnit.MILLIBITCOIN:
|
|
123
|
+
return "Millibitcoins";
|
|
124
|
+
case CurrencyUnit.MICROBITCOIN:
|
|
125
|
+
return "Microbitcoins";
|
|
126
|
+
case CurrencyUnit.NANOBITCOIN:
|
|
127
|
+
return "Nanobitcoins";
|
|
128
|
+
case CurrencyUnit.SATOSHI:
|
|
129
|
+
return "Satoshis";
|
|
130
|
+
case CurrencyUnit.MILLISATOSHI:
|
|
131
|
+
return "Millisatoshis";
|
|
132
|
+
}
|
|
133
|
+
return unit;
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
const shorttext = (unit: CurrencyUnit) => {
|
|
137
|
+
switch (unit) {
|
|
138
|
+
case CurrencyUnit.BITCOIN:
|
|
139
|
+
return "BTC";
|
|
140
|
+
case CurrencyUnit.MILLIBITCOIN:
|
|
141
|
+
return "mBTC";
|
|
142
|
+
case CurrencyUnit.MICROBITCOIN:
|
|
143
|
+
return "μBTC";
|
|
144
|
+
case CurrencyUnit.SATOSHI:
|
|
145
|
+
return "sat";
|
|
146
|
+
case CurrencyUnit.MILLISATOSHI:
|
|
147
|
+
return "msat";
|
|
148
|
+
}
|
|
149
|
+
return unit;
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
// This is a squared-off version that is compatible with Montserrat.
|
|
153
|
+
type SatProps = {
|
|
154
|
+
color?: string;
|
|
155
|
+
offset?: number;
|
|
156
|
+
size?: number;
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
const Satoshi = (props: SatProps) => (
|
|
160
|
+
<svg
|
|
161
|
+
width="0.675em"
|
|
162
|
+
height="0.9em"
|
|
163
|
+
style={{ transform: "translate(-0.05em, 0.1em)" }}
|
|
164
|
+
viewBox="0 0 26 40"
|
|
165
|
+
fill="none"
|
|
166
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
167
|
+
>
|
|
168
|
+
<rect y="8.88867" width="25.9994" height="4.44434" fill="currentColor" />
|
|
169
|
+
<rect y="17.7788" width="25.9994" height="4.44434" fill="currentColor" />
|
|
170
|
+
<rect y="26.6685" width="25.9994" height="4.44434" fill="currentColor" />
|
|
171
|
+
<rect
|
|
172
|
+
x="15.4753"
|
|
173
|
+
y="34.6748"
|
|
174
|
+
width="5.32497"
|
|
175
|
+
height="4.95226"
|
|
176
|
+
transform="rotate(90 15.4753 34.6748)"
|
|
177
|
+
fill="currentColor"
|
|
178
|
+
/>
|
|
179
|
+
<rect
|
|
180
|
+
x="15.4753"
|
|
181
|
+
width="5.33322"
|
|
182
|
+
height="4.95226"
|
|
183
|
+
transform="rotate(90 15.4753 0)"
|
|
184
|
+
fill="currentColor"
|
|
185
|
+
/>
|
|
186
|
+
</svg>
|
|
187
|
+
);
|
|
188
|
+
|
|
189
|
+
const Amount = styled.span`
|
|
190
|
+
color: inherit !important;
|
|
191
|
+
white-space: nowrap;
|
|
192
|
+
font-feature-settings: "tnum" on, "lnum" on;
|
|
193
|
+
`;
|
|
194
|
+
|
|
195
|
+
export default CurrencyAmountRaw;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// Copyright ©, 2022, Lightspark Group, Inc. - All Rights Reserved
|
|
2
|
+
|
|
3
|
+
const LeftArrow = () => (
|
|
4
|
+
<svg
|
|
5
|
+
width="16"
|
|
6
|
+
height="16"
|
|
7
|
+
viewBox="0 0 16 16"
|
|
8
|
+
fill="none"
|
|
9
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
10
|
+
>
|
|
11
|
+
<path
|
|
12
|
+
d="M12.9837 8.00003L3.01636 8.00003M3.01636 8.00003L7.01636 12.1905M3.01636 8.00003L7.01636 3.80955"
|
|
13
|
+
stroke="#666666"
|
|
14
|
+
stroke-width="1.33333"
|
|
15
|
+
stroke-linecap="round"
|
|
16
|
+
stroke-linejoin="round"
|
|
17
|
+
/>
|
|
18
|
+
</svg>
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
export default LeftArrow;
|