Skip to content

Commit 33702d2

Browse files
authored
feat: replace pouchdb with extension storage (#1582)
* chore: bump cardano-js-sdk * refactor: replace pouchdb indexeddb storage with extension storage * perf: render loader sooner
1 parent 45a07fd commit 33702d2

File tree

33 files changed

+713
-105
lines changed

33 files changed

+713
-105
lines changed

apps/browser-extension-wallet/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,8 @@
4848
"@cardano-sdk/tx-construction": "0.23.0",
4949
"@cardano-sdk/util": "0.15.5",
5050
"@cardano-sdk/util-rxjs": "0.8.0",
51-
"@cardano-sdk/wallet": "0.46.0",
52-
"@cardano-sdk/web-extension": "0.34.24",
51+
"@cardano-sdk/wallet": "0.46.2",
52+
"@cardano-sdk/web-extension": "0.36.1",
5353
"@emurgo/cip14-js": "~3.0.1",
5454
"@input-output-hk/lace-ui-toolkit": "1.21.0",
5555
"@lace/cardano": "0.1.0",

apps/browser-extension-wallet/src/assets/html/app.html

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,27 @@
66
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
77
<link rel="preconnect" href="https://use.typekit.net" crossorigin />
88
<link rel="stylesheet" href="https://use.typekit.net/ksk5ywd.css" />
9+
<link rel="stylesheet" href="preloader.css" />
10+
<style>
11+
html,
12+
head,
13+
body {
14+
margin: 0;
15+
padding: 0;
16+
width: 100vw;
17+
height: 100vh;
18+
}
19+
</style>
20+
<script src="js/load-app.js"></script>
921
<title>Lace</title>
1022
</head>
1123
<body>
24+
<div id="preloader" class="overlay loaderContainer" data-testid="preloader">
25+
<div class="imageContainer">
26+
<img alt="loader" src="loader.png" class="loaderImage" data-testid="preloader-image" />
27+
</div>
28+
<p class="loaderText" data-testid="preloader-text">Loading...</p>
29+
</div>
1230
<div id="lace-app"></div>
1331
</body>
1432
</html>
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
6+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
7+
<link rel="preconnect" href="https://use.typekit.net" crossorigin />
8+
<link rel="stylesheet" href="https://use.typekit.net/ksk5ywd.css" />
9+
10+
<title>Lace</title>
11+
<link rel="stylesheet" href="preloader.css" />
12+
<style>
13+
html,
14+
head,
15+
body {
16+
height: 600px;
17+
width: 360px;
18+
margin: 0;
19+
padding: 0;
20+
}
21+
</style>
22+
<script src="js/load-dapp-connector.js"></script>
23+
</head>
24+
<body id="lace-popup-body">
25+
<div id="preloader" class="overlay loaderContainer" data-testid="preloader">
26+
<div class="imageContainer">
27+
<img alt="loader" src="loader.png" class="loaderImage" data-testid="preloader-image" />
28+
</div>
29+
<p class="loaderText" data-testid="preloader-text">Loading...</p>
30+
</div>
31+
<div id="lace-popup"></div>
32+
</body>
33+
</html>
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
window.addEventListener(
2+
'load',
3+
() => {
4+
const script = document.createElement('script');
5+
script.setAttribute('src', 'js/options.js');
6+
document.head.appendChild(script);
7+
},
8+
{ once: true }
9+
);
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
window.addEventListener(
2+
'load',
3+
() => {
4+
const script = document.createElement('script');
5+
script.setAttribute('src', 'js/dappConnector.js');
6+
document.head.appendChild(script);
7+
},
8+
{ once: true }
9+
);
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
window.addEventListener(
2+
'load',
3+
() => {
4+
const script = document.createElement('script');
5+
script.setAttribute('src', 'js/popup.js');
6+
document.head.appendChild(script);
7+
},
8+
{ once: true }
9+
);

apps/browser-extension-wallet/src/assets/html/popup.html

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,28 @@
66
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
77
<link rel="preconnect" href="https://use.typekit.net" crossorigin />
88
<link rel="stylesheet" href="https://use.typekit.net/ksk5ywd.css" />
9+
910
<title>Lace</title>
11+
<link rel="stylesheet" href="preloader.css" />
1012
<style>
13+
html,
14+
head,
1115
body {
1216
height: 600px;
17+
width: 360px;
18+
margin: 0;
19+
padding: 0;
1320
}
1421
</style>
22+
<script src="js/load-popup.js"></script>
1523
</head>
1624
<body id="lace-popup-body">
25+
<div id="preloader" class="overlay loaderContainer" data-testid="preloader">
26+
<div class="imageContainer">
27+
<img alt="loader" src="loader.png" class="loaderImage" data-testid="preloader-image" />
28+
</div>
29+
<p class="loaderText" data-testid="preloader-text">Loading...</p>
30+
</div>
1731
<div id="lace-popup"></div>
1832
</body>
1933
</html>
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
.loaderContainer {
2+
display: flex;
3+
align-items: center;
4+
justify-content: center;
5+
flex-direction: column;
6+
gap: 16px;
7+
position: fixed;
8+
width: 100%;
9+
height: 100%;
10+
top: 0;
11+
left: 0;
12+
right: 0;
13+
bottom: 0;
14+
background-color: #fff;
15+
z-index: 2000;
16+
}
17+
18+
.loaderContainer .loaderText {
19+
color: #3d3b39;
20+
font-family: 'proxima-nova', sans-serif;
21+
font-variant: tabular-nums;
22+
line-height: 1.5715;
23+
font-feature-settings: 'tnum';
24+
font-size: 14px;
25+
margin-top: 0;
26+
margin-bottom: 1em;
27+
}
28+
29+
@keyframes rotating {
30+
from {
31+
transform: rotate(0deg);
32+
}
33+
to {
34+
transform: rotate(360deg);
35+
}
36+
}
37+
38+
.loaderContainer .imageContainer {
39+
height: 126px;
40+
width: 126px;
41+
}
42+
43+
.loaderContainer .loaderImage {
44+
animation: rotating 2s linear infinite;
45+
width: 100%;
46+
height: 100%;
47+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/* eslint-disable @typescript-eslint/ban-types, brace-style */
2+
import { ExtensionDocumentStore } from './extension-document-store';
3+
import { storage as sdkStorage } from '@cardano-sdk/wallet';
4+
import { Logger } from 'ts-log';
5+
import { concat, defaultIfEmpty, EMPTY, filter, map, mergeMap, Observable, of } from 'rxjs';
6+
import { isNotNil } from '@cardano-sdk/util';
7+
8+
/**
9+
* Stores entire collection in a single document
10+
*/
11+
export class ExtensionBlobCollectionStore<T extends {}>
12+
extends ExtensionDocumentStore<T[]>
13+
implements sdkStorage.CollectionStore<T>
14+
{
15+
/**
16+
* @param collectionName used as extension storage key
17+
*/
18+
constructor(collectionName: string, logger: Logger) {
19+
super(collectionName, logger);
20+
}
21+
22+
observeAll(): Observable<T[]> {
23+
return concat(
24+
this.get().pipe(defaultIfEmpty([])),
25+
this.documentChange$.pipe(
26+
map(({ newValue }) => newValue),
27+
filter(isNotNil)
28+
)
29+
);
30+
}
31+
32+
getAll(): Observable<T[]> {
33+
return this.get().pipe(mergeMap((items) => (items.length > 0 ? of(items) : EMPTY)));
34+
}
35+
36+
setAll(docs: T[]): Observable<void> {
37+
return this.set(docs);
38+
}
39+
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/* eslint-disable @typescript-eslint/ban-types, brace-style */
2+
import { ExtensionDocumentStore } from './extension-document-store';
3+
import { storage as sdkStorage } from '@cardano-sdk/wallet';
4+
import { Logger } from 'ts-log';
5+
import { defaultIfEmpty, EMPTY, firstValueFrom, from, mergeMap, Observable, of } from 'rxjs';
6+
import { OpaqueString, toSerializableObject } from '@cardano-sdk/util';
7+
8+
/**
9+
* Stores entire key-value collection in a single document
10+
*/
11+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
12+
export class ExtensionBlobKeyValueStore<K extends string | OpaqueString<any>, V extends {}>
13+
extends ExtensionDocumentStore<Record<K, V>>
14+
implements sdkStorage.KeyValueStore<K, V>
15+
{
16+
/**
17+
* @param collectionName used as extension storage key
18+
*/
19+
constructor(collectionName: string, logger: Logger) {
20+
super(collectionName, logger);
21+
}
22+
23+
getValues(keys: K[]): Observable<V[]> {
24+
return this.get().pipe(
25+
mergeMap((collection): Observable<V[]> => {
26+
const values: V[] = [];
27+
for (const key of keys) {
28+
const value = collection[key];
29+
if (!value) {
30+
this.logger.debug(`Key "$${key}" was not found`);
31+
return EMPTY;
32+
}
33+
values.push(value);
34+
}
35+
return of(values);
36+
})
37+
);
38+
}
39+
40+
setValue(key: K, value: V): Observable<void> {
41+
return from(
42+
(this.idle = this.idle.then(async () => {
43+
const collection = await firstValueFrom(this.get().pipe(defaultIfEmpty({} as Record<K, V>)));
44+
return this.storage.set({
45+
[this.docId]: toSerializableObject({
46+
...collection,
47+
[key]: value
48+
})
49+
});
50+
}))
51+
);
52+
}
53+
54+
setAll(docs: sdkStorage.KeyValueCollection<K, V>[]): Observable<void> {
55+
return this.set(
56+
docs.reduce((collection, { key, value }) => {
57+
collection[key] = value;
58+
return collection;
59+
}, {} as Record<K, V>)
60+
);
61+
}
62+
}

0 commit comments

Comments
 (0)