Skip to content
This repository was archived by the owner on Apr 21, 2025. It is now read-only.

Commit 619eb76

Browse files
committed
Background android app pending payments
1 parent ff93a0e commit 619eb76

7 files changed

Lines changed: 130 additions & 2 deletions

File tree

android/app/capacitor.build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ apply from: "../capacitor-cordova-android-plugins/cordova.variables.gradle"
1111
dependencies {
1212
implementation project(':capacitor-mlkit-barcode-scanning')
1313
implementation project(':capacitor-app')
14+
implementation project(':capacitor-background-runner')
1415
implementation project(':capacitor-browser')
1516
implementation project(':capacitor-clipboard')
1617
implementation project(':capacitor-filesystem')

android/app/src/main/AndroidManifest.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,4 +60,6 @@
6060
<uses-permission android:name="android.permission.WRITE_CLIPBOARD" />
6161
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
6262
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
63+
64+
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
6365
</manifest>

android/capacitor.settings.gradle

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ project(':capacitor-mlkit-barcode-scanning').projectDir = new File('../node_modu
88
include ':capacitor-app'
99
project(':capacitor-app').projectDir = new File('../node_modules/.pnpm/@capacitor+app@5.0.6_@capacitor+core@5.5.1/node_modules/@capacitor/app/android')
1010

11+
include ':capacitor-background-runner'
12+
project(':capacitor-background-runner').projectDir = new File('../node_modules/.pnpm/@capacitor+background-runner@1.0.5_@capacitor+core@5.2.2/node_modules/@capacitor/background-runner/android')
13+
1114
include ':capacitor-browser'
1215
project(':capacitor-browser').projectDir = new File('../node_modules/.pnpm/@capacitor+browser@5.0.6_@capacitor+core@5.5.1/node_modules/@capacitor/browser/android')
1316

capacitor.config.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,17 @@ const config: CapacitorConfig = {
77
webDir: 'dist/public',
88
server: {
99
androidScheme: 'https'
10-
}
10+
},
11+
plugins: {
12+
BackgroundRunner: {
13+
label: 'com.mutinywallet.mutinywallet.background',
14+
src: 'runners/background.ts',
15+
event: 'checkPaymentsInFlight',
16+
repeat: true,
17+
interval: 60,
18+
autoStart: true,
19+
},
20+
},
1121
};
1222

1323
export default config;

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,8 @@
4545
"@capacitor-mlkit/barcode-scanning": "^5.3.0",
4646
"@capacitor/android": "^5.5.1",
4747
"@capacitor/app": "^5.0.6",
48-
"@capacitor/browser": "5.0.6",
48+
"@capacitor/background-runner": "1.0.5",
49+
"@capacitor/browser": "5.0.6",
4950
"@capacitor/clipboard": "^5.0.6",
5051
"@capacitor/core": "^5.5.1",
5152
"@capacitor/filesystem": "^5.1.4",

pnpm-lock.yaml

Lines changed: 12 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/runners/background.ts

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
import { CapacitorNotifications } from "@capacitor/background-runner";
2+
3+
addEventListener("checkPaymentsInFlight", async (resolve, reject, _args) => {
4+
try {
5+
await checkPaymentsInFlight();
6+
resolve();
7+
} catch (e) {
8+
reject(e);
9+
}
10+
});
11+
12+
interface OutboundPayment {
13+
status: string;
14+
}
15+
16+
async function checkPaymentsInFlight() {
17+
console.log("checkPaymentsInFlight");
18+
const db = await openDatabase();
19+
20+
const transaction = db.transaction("wallet_store", "readonly");
21+
const store = transaction.objectStore("wallet_store");
22+
23+
// Get keys prefixed with "payment_outbound"
24+
const keys = await getAllKeysWithPrefix(store, "payment_outbound");
25+
26+
for (const key of keys) {
27+
const payment = await get(store, key);
28+
console.log(payment.status);
29+
// fixme change back to InFlight
30+
if (payment && payment.status === "Succeeded") {
31+
showNotification();
32+
break;
33+
}
34+
}
35+
transaction.commit();
36+
}
37+
38+
function openDatabase(): Promise<IDBDatabase> {
39+
return new Promise((resolve, reject) => {
40+
const request = indexedDB.open("wallet");
41+
request.onsuccess = () => resolve(request.result);
42+
request.onerror = () => reject(request.error);
43+
});
44+
}
45+
46+
function getAllKeysWithPrefix(
47+
store: IDBObjectStore,
48+
prefix: string
49+
): Promise<string[]> {
50+
return new Promise((resolve, reject) => {
51+
const keys: string[] = [];
52+
const cursorRequest = store.openKeyCursor();
53+
54+
cursorRequest.onsuccess = function (event) {
55+
const cursor = (event.target as IDBRequest).result as IDBCursor;
56+
if (cursor) {
57+
if (cursor.key.toString().startsWith(prefix)) {
58+
keys.push(cursor.key.toString());
59+
}
60+
cursor.continue();
61+
} else {
62+
resolve(keys);
63+
}
64+
};
65+
66+
cursorRequest.onerror = function () {
67+
reject(cursorRequest.error);
68+
};
69+
});
70+
}
71+
72+
function get(store: IDBObjectStore, key: string): Promise<OutboundPayment> {
73+
return new Promise((resolve, reject) => {
74+
const request = store.get(key);
75+
request.onsuccess = () => resolve(request.result);
76+
request.onerror = () => reject(request.error);
77+
});
78+
}
79+
80+
function showNotification() {
81+
// generate random id
82+
const id = Math.random() * 100_000_000;
83+
84+
// send notification in 5 seconds
85+
const scheduleDate = new Date();
86+
scheduleDate.setSeconds(scheduleDate.getSeconds() + 5);
87+
88+
// todo make pretty
89+
CapacitorNotifications.schedule([
90+
{
91+
id,
92+
title: "You have a payment in flight",
93+
body: "Open Mutiny to make sure it completes.",
94+
scheduleAt: scheduleDate
95+
}
96+
]);
97+
}
98+
99+
export default checkPaymentsInFlight;

0 commit comments

Comments
 (0)