Skip to content

Commit

Permalink
Background android app pending payments
Browse files Browse the repository at this point in the history
  • Loading branch information
benthecarman committed Nov 11, 2023
1 parent ff93a0e commit 619eb76
Show file tree
Hide file tree
Showing 7 changed files with 130 additions and 2 deletions.
1 change: 1 addition & 0 deletions android/app/capacitor.build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ apply from: "../capacitor-cordova-android-plugins/cordova.variables.gradle"
dependencies {
implementation project(':capacitor-mlkit-barcode-scanning')
implementation project(':capacitor-app')
implementation project(':capacitor-background-runner')
implementation project(':capacitor-browser')
implementation project(':capacitor-clipboard')
implementation project(':capacitor-filesystem')
Expand Down
2 changes: 2 additions & 0 deletions android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -60,4 +60,6 @@
<uses-permission android:name="android.permission.WRITE_CLIPBOARD" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
</manifest>
3 changes: 3 additions & 0 deletions android/capacitor.settings.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ project(':capacitor-mlkit-barcode-scanning').projectDir = new File('../node_modu
include ':capacitor-app'
project(':capacitor-app').projectDir = new File('../node_modules/.pnpm/@capacitor+app@5.0.6_@capacitor+core@5.5.1/node_modules/@capacitor/app/android')

include ':capacitor-background-runner'
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')

include ':capacitor-browser'
project(':capacitor-browser').projectDir = new File('../node_modules/.pnpm/@capacitor+browser@5.0.6_@capacitor+core@5.5.1/node_modules/@capacitor/browser/android')

Expand Down
12 changes: 11 additions & 1 deletion capacitor.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,17 @@ const config: CapacitorConfig = {
webDir: 'dist/public',
server: {
androidScheme: 'https'
}
},
plugins: {
BackgroundRunner: {
label: 'com.mutinywallet.mutinywallet.background',
src: 'runners/background.ts',
event: 'checkPaymentsInFlight',
repeat: true,
interval: 60,
autoStart: true,
},
},
};

export default config;
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@
"@capacitor-mlkit/barcode-scanning": "^5.3.0",
"@capacitor/android": "^5.5.1",
"@capacitor/app": "^5.0.6",
"@capacitor/browser": "5.0.6",
"@capacitor/background-runner": "1.0.5",
"@capacitor/browser": "5.0.6",
"@capacitor/clipboard": "^5.0.6",
"@capacitor/core": "^5.5.1",
"@capacitor/filesystem": "^5.1.4",
Expand Down
12 changes: 12 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

99 changes: 99 additions & 0 deletions src/runners/background.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import { CapacitorNotifications } from "@capacitor/background-runner";

addEventListener("checkPaymentsInFlight", async (resolve, reject, _args) => {

Check failure on line 3 in src/runners/background.ts

View workflow job for this annotation

GitHub Actions / code_quality

No overload matches this call.

Check failure on line 3 in src/runners/background.ts

View workflow job for this annotation

GitHub Actions / code_quality

Parameter 'resolve' implicitly has an 'any' type.

Check failure on line 3 in src/runners/background.ts

View workflow job for this annotation

GitHub Actions / code_quality

Parameter 'reject' implicitly has an 'any' type.

Check failure on line 3 in src/runners/background.ts

View workflow job for this annotation

GitHub Actions / code_quality

Parameter '_args' implicitly has an 'any' type.
try {
await checkPaymentsInFlight();
resolve();
} catch (e) {
reject(e);
}
});

interface OutboundPayment {
status: string;
}

async function checkPaymentsInFlight() {
console.log("checkPaymentsInFlight");
const db = await openDatabase();

const transaction = db.transaction("wallet_store", "readonly");
const store = transaction.objectStore("wallet_store");

// Get keys prefixed with "payment_outbound"
const keys = await getAllKeysWithPrefix(store, "payment_outbound");

for (const key of keys) {
const payment = await get(store, key);
console.log(payment.status);
// fixme change back to InFlight
if (payment && payment.status === "Succeeded") {
showNotification();
break;
}
}
transaction.commit();
}

function openDatabase(): Promise<IDBDatabase> {
return new Promise((resolve, reject) => {
const request = indexedDB.open("wallet");
request.onsuccess = () => resolve(request.result);
request.onerror = () => reject(request.error);
});
}

function getAllKeysWithPrefix(
store: IDBObjectStore,
prefix: string
): Promise<string[]> {
return new Promise((resolve, reject) => {
const keys: string[] = [];
const cursorRequest = store.openKeyCursor();

cursorRequest.onsuccess = function (event) {
const cursor = (event.target as IDBRequest).result as IDBCursor;
if (cursor) {
if (cursor.key.toString().startsWith(prefix)) {
keys.push(cursor.key.toString());
}
cursor.continue();
} else {
resolve(keys);
}
};

cursorRequest.onerror = function () {
reject(cursorRequest.error);
};
});
}

function get(store: IDBObjectStore, key: string): Promise<OutboundPayment> {
return new Promise((resolve, reject) => {
const request = store.get(key);
request.onsuccess = () => resolve(request.result);
request.onerror = () => reject(request.error);
});
}

function showNotification() {
// generate random id
const id = Math.random() * 100_000_000;

// send notification in 5 seconds
const scheduleDate = new Date();
scheduleDate.setSeconds(scheduleDate.getSeconds() + 5);

// todo make pretty
CapacitorNotifications.schedule([

Check failure on line 89 in src/runners/background.ts

View workflow job for this annotation

GitHub Actions / code_quality

'CapacitorNotifications' only refers to a type, but is being used as a value here.
{
id,
title: "You have a payment in flight",
body: "Open Mutiny to make sure it completes.",
scheduleAt: scheduleDate
}
]);
}

export default checkPaymentsInFlight;

0 comments on commit 619eb76

Please sign in to comment.