Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Display pending nwc from dms #834

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions android/app/capacitor.build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ dependencies {
implementation project(':capacitor-share')
implementation project(':capacitor-status-bar')
implementation project(':capacitor-toast')
implementation project(':capacitor-secure-storage-plugin')

}

Expand Down
3 changes: 3 additions & 0 deletions android/capacitor.settings.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,6 @@ project(':capacitor-status-bar').projectDir = new File('../node_modules/.pnpm/@c

include ':capacitor-toast'
project(':capacitor-toast').projectDir = new File('../node_modules/.pnpm/@[email protected]_@[email protected]/node_modules/@capacitor/toast/android')

include ':capacitor-secure-storage-plugin'
project(':capacitor-secure-storage-plugin').projectDir = new File('../node_modules/.pnpm/[email protected]_@[email protected]/node_modules/capacitor-secure-storage-plugin/android')
1 change: 1 addition & 0 deletions ios/App/Podfile
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ def capacitor_pods
pod 'CapacitorShare', :path => '../../node_modules/.pnpm/@[email protected]_@[email protected]/node_modules/@capacitor/share'
pod 'CapacitorStatusBar', :path => '../../node_modules/.pnpm/@[email protected]_@[email protected]/node_modules/@capacitor/status-bar'
pod 'CapacitorToast', :path => '../../node_modules/.pnpm/@[email protected]_@[email protected]/node_modules/@capacitor/toast'
pod 'CapacitorSecureStoragePlugin', :path => '../../node_modules/.pnpm/[email protected]_@[email protected]/node_modules/capacitor-secure-storage-plugin'
end

target 'App' do
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
"@solid-primitives/upload": "^0.0.111",
"@solidjs/meta": "^0.29.1",
"@solidjs/router": "^0.9.0",
"capacitor-secure-storage-plugin": "^0.9.0",
"i18next": "^22.5.1",
"i18next-browser-languagedetector": "^7.1.0",
"qr-scanner": "^1.4.2",
Expand Down
11 changes: 11 additions & 0 deletions pnpm-lock.yaml

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

15 changes: 15 additions & 0 deletions src/components/PendingNwc.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { TagItem } from "@mutinywallet/mutiny-wasm";
import {
createEffect,
createResource,
Expand Down Expand Up @@ -44,6 +45,10 @@
const profiles = await state.mutiny_wallet?.get_nwc_profiles();
if (!profiles) return [];

const contacts: TagItem[] | undefined =
await state.mutiny_wallet?.get_contacts_sorted();
if (!contacts) return [];

const pending = await state.mutiny_wallet?.get_pending_nwc_invoices();
if (!pending) return [];

Expand All @@ -59,6 +64,16 @@
date: p.expiry,
amount_sats: p.amount_sats
});
} else {
const contact = contacts.find((c) => c.npub === p.npub);

Check failure on line 68 in src/components/PendingNwc.tsx

View workflow job for this annotation

GitHub Actions / Build APK

Property 'npub' does not exist on type 'PendingNwcInvoice'.

Check failure on line 68 in src/components/PendingNwc.tsx

View workflow job for this annotation

GitHub Actions / code_quality

Property 'npub' does not exist on type 'PendingNwcInvoice'.

Check failure on line 68 in src/components/PendingNwc.tsx

View workflow job for this annotation

GitHub Actions / Build iOS

Property 'npub' does not exist on type 'PendingNwcInvoice'.
if (contact) {
pendingItems.push({
id: p.id,
name_of_connection: contact.name,
date: p.expiry,
amount_sats: p.amount_sats
});
}
}
}
return pendingItems;
Expand Down
5 changes: 1 addition & 4 deletions src/components/SyncContactsForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@
npub: string;
};

const PRIMAL_API = import.meta.env.VITE_PRIMAL;

export function SyncContactsForm() {
const i18n = useI18n();
const [state, actions] = useMegaStore();
Expand All @@ -30,8 +28,7 @@
) => {
try {
const npub = f.npub.trim();
if (!PRIMAL_API) throw new Error("PRIMAL_API not set");
await state.mutiny_wallet?.sync_nostr_contacts(PRIMAL_API, npub);
await state.mutiny_wallet?.sync_nostr_contacts(npub);

Check failure on line 31 in src/components/SyncContactsForm.tsx

View workflow job for this annotation

GitHub Actions / Build APK

Expected 2 arguments, but got 1.

Check failure on line 31 in src/components/SyncContactsForm.tsx

View workflow job for this annotation

GitHub Actions / code_quality

Expected 2 arguments, but got 1.

Check failure on line 31 in src/components/SyncContactsForm.tsx

View workflow job for this annotation

GitHub Actions / Build iOS

Expected 2 arguments, but got 1.
actions.saveNpub(npub);
} catch (e) {
console.error(e);
Expand Down
40 changes: 38 additions & 2 deletions src/logic/mutinyWalletSetup.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
/* @refresh reload */

import { Capacitor } from "@capacitor/core";
import initMutinyWallet, { MutinyWallet } from "@mutinywallet/mutiny-wasm";
import { SecureStoragePlugin } from "capacitor-secure-storage-plugin";

export type Network = "bitcoin" | "testnet" | "regtest" | "signet";

Expand All @@ -16,6 +18,7 @@
subscriptions?: string;
storage?: string;
scorer?: string;
primal?: string;
selfhosted?: string;
};

Expand Down Expand Up @@ -75,6 +78,11 @@
storageKey: "USER_SETTINGS_scorer",
default: import.meta.env.VITE_SCORER
},
{
name: "primal",
storageKey: "USER_SETTINGS_primal",
default: import.meta.env.VITE_PRIMAL
},
{
name: "selfhosted",
storageKey: "USER_SETTINGS_selfhosted",
Expand Down Expand Up @@ -246,9 +254,33 @@
auth,
subscriptions,
storage,
scorer
scorer,
primal
} = settings;

let nsec;
// get nsec from secure storage
if (Capacitor.isNativePlatform()) {
try {
const value = await SecureStoragePlugin.get({ key: "nsec" });
nsec = value.value;
} catch (e) {
console.log("No nsec stored");
}
}

// if we didn't get an nsec from storage, try to use extension
let extension_key;
if (!nsec) {
try {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore ignore nostr not existing, only does if they have extension
extension_key = await window.nostr.getPublicKey();
} catch (_) {
console.log("No NIP-07 extension");
}
}

console.log("Initializing Mutiny Manager");
console.log("Using network", network);
console.log("Using proxy", proxy);
Expand All @@ -261,6 +293,7 @@
console.log("Using subscriptions address", subscriptions);
console.log("Using storage address", storage);
console.log("Using scorer address", scorer);
console.log("Using primal address", primal);
console.log(safeMode ? "Safe mode enabled" : "Safe mode disabled");
console.log(shouldZapHodl ? "Hodl zaps enabled" : "Hodl zaps disabled");

Expand Down Expand Up @@ -290,7 +323,10 @@
// Safe mode
safeMode || undefined,
// Skip hodl invoices? (defaults to true, so if shouldZapHodl is true that's when we pass false)
shouldZapHodl ? false : undefined
shouldZapHodl ? false : undefined,
nsec,

Check failure on line 327 in src/logic/mutinyWalletSetup.ts

View workflow job for this annotation

GitHub Actions / Build APK

Expected 0-17 arguments, but got 20.

Check failure on line 327 in src/logic/mutinyWalletSetup.ts

View workflow job for this annotation

GitHub Actions / code_quality

Expected 0-17 arguments, but got 20.

Check failure on line 327 in src/logic/mutinyWalletSetup.ts

View workflow job for this annotation

GitHub Actions / Build iOS

Expected 0-17 arguments, but got 20.
extension_key ? extension_key : undefined,
primal
);

sessionStorage.setItem("MUTINY_WALLET_INITIALIZED", Date.now().toString());
Expand Down
40 changes: 31 additions & 9 deletions src/routes/settings/SyncNostrContacts.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import { Capacitor } from "@capacitor/core";
import { createForm, required, SubmitHandler } from "@modular-forms/solid";
import { MutinyWallet } from "@mutinywallet/mutiny-wasm";
import { SecureStoragePlugin } from "capacitor-secure-storage-plugin";
import { createSignal, Match, Show, Switch } from "solid-js";

import {
Expand All @@ -24,13 +27,13 @@
npub: string;
};

const PRIMAL_API = import.meta.env.VITE_PRIMAL;

function SyncContactsForm() {
const i18n = useI18n();
const [state, actions] = useMegaStore();
const [error, setError] = createSignal<Error>();

const allowNsec = Capacitor.isNativePlatform();

const [feedbackForm, { Form, Field }] = createForm<NostrContactsForm>({
initialValues: {
npub: ""
Expand All @@ -41,9 +44,27 @@
f: NostrContactsForm
) => {
try {
const npub = f.npub.trim();
if (!PRIMAL_API) throw new Error("PRIMAL_API not set");
await state.mutiny_wallet?.sync_nostr_contacts(PRIMAL_API, npub);
const string = f.npub.trim();
let npub = string;

// if it is an nsec, save it into secure storage
if (string.startsWith("nsec")) {
if (!allowNsec) {
throw new Error(
"nsec not allowed in web version, please install the app"
);
}

// set in storage
SecureStoragePlugin.set({ key: "nsec", value: string }).then(
(success) => console.log(success)
);

// set npub and continue
npub = await MutinyWallet.nsec_to_npub(string);

Check failure on line 64 in src/routes/settings/SyncNostrContacts.tsx

View workflow job for this annotation

GitHub Actions / Build APK

Property 'nsec_to_npub' does not exist on type 'typeof MutinyWallet'.

Check failure on line 64 in src/routes/settings/SyncNostrContacts.tsx

View workflow job for this annotation

GitHub Actions / code_quality

Property 'nsec_to_npub' does not exist on type 'typeof MutinyWallet'.

Check failure on line 64 in src/routes/settings/SyncNostrContacts.tsx

View workflow job for this annotation

GitHub Actions / Build iOS

Property 'nsec_to_npub' does not exist on type 'typeof MutinyWallet'.
}

await state.mutiny_wallet?.sync_nostr_contacts(npub);

Check failure on line 67 in src/routes/settings/SyncNostrContacts.tsx

View workflow job for this annotation

GitHub Actions / Build APK

Expected 2 arguments, but got 1.

Check failure on line 67 in src/routes/settings/SyncNostrContacts.tsx

View workflow job for this annotation

GitHub Actions / code_quality

Expected 2 arguments, but got 1.

Check failure on line 67 in src/routes/settings/SyncNostrContacts.tsx

View workflow job for this annotation

GitHub Actions / Build iOS

Expected 2 arguments, but got 1.
actions.saveNpub(npub);
} catch (e) {
console.error(e);
Expand All @@ -68,7 +89,7 @@
value={field.value}
error={field.error}
label={i18n.t("settings.nostr_contacts.npub_label")}
placeholder="npub..."
placeholder={allowNsec ? "npub/nsec..." : "npub..."}
/>
)}
</Field>
Expand Down Expand Up @@ -97,17 +118,18 @@
const [loading, setLoading] = createSignal(false);
const [error, setError] = createSignal<Error>();

function clearNpub() {
async function clearNpub() {
actions.saveNpub("");
if (Capacitor.isNativePlatform()) {
await SecureStoragePlugin.remove({ key: "nsec" });
}
}

async function resync() {
setError(undefined);
setLoading(true);
try {
if (!PRIMAL_API) throw new Error("PRIMAL_API not set");
await state.mutiny_wallet?.sync_nostr_contacts(

Check failure on line 132 in src/routes/settings/SyncNostrContacts.tsx

View workflow job for this annotation

GitHub Actions / Build APK

Expected 2 arguments, but got 1.

Check failure on line 132 in src/routes/settings/SyncNostrContacts.tsx

View workflow job for this annotation

GitHub Actions / code_quality

Expected 2 arguments, but got 1.

Check failure on line 132 in src/routes/settings/SyncNostrContacts.tsx

View workflow job for this annotation

GitHub Actions / Build iOS

Expected 2 arguments, but got 1.
PRIMAL_API,
// We can only see the resync button if there's an npub set
state.npub!
);
Expand Down
24 changes: 17 additions & 7 deletions src/utils/fetchZaps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,9 +116,13 @@ async function simpleZapFromEvent(
}
}

// todo remove
const PRIMAL_API = import.meta.env.VITE_PRIMAL;

async function fetchFollows(npub: string): Promise<string[]> {
async function fetchFollows(
primal_url: string,
npub: string
): Promise<string[]> {
let pubkey = undefined;
try {
pubkey = await hexpubFromNpub(npub);
Expand All @@ -127,7 +131,7 @@ async function fetchFollows(npub: string): Promise<string[]> {
throw err;
}

const response = await fetch(PRIMAL_API, {
const response = await fetch(primal_url, {
method: "POST",
headers: {
"Content-Type": "application/json"
Expand Down Expand Up @@ -167,9 +171,10 @@ type PrimalResponse = NostrEvent | NostrProfile;

async function fetchZapsFromPrimal(
follows: string[],
primal_url?: string,
until?: number
): Promise<PrimalResponse[]> {
if (!PRIMAL_API) throw new Error("Missing PRIMAL_API environment variable");
if (!primal_url) throw new Error("Missing PRIMAL_API environment variable");

const query = {
kinds: [9735, 0, 10000113],
Expand All @@ -183,7 +188,7 @@ async function fetchZapsFromPrimal(
until ? { ...query, since: until } : query
]);

const response = await fetch(PRIMAL_API, {
const response = await fetch(primal_url, {
method: "POST",
headers: {
"Content-Type": "application/json"
Expand Down Expand Up @@ -224,16 +229,21 @@ export const fetchZaps: ResourceFetcher<
info.value?.profiles || {};
let newUntil = undefined;

if (!PRIMAL_API)
const primal_url = state.settings?.primal;
if (!primal_url)
throw new Error("Missing PRIMAL_API environment variable");

// Only have to ask the relays for follows one time
if (follows.length === 0) {
follows = await fetchFollows(npub);
follows = await fetchFollows(primal_url, npub);
}

// Ask primal for all the zaps for these follow pubkeys
const data = await fetchZapsFromPrimal(follows, info?.value?.until);
const data = await fetchZapsFromPrimal(
follows,
primal_url,
info?.value?.until
);

// Parse the primal response
for (const object of data) {
Expand Down
Loading