Skip to content

Commit

Permalink
Merge pull request #9 from getAlby/feat/address-book
Browse files Browse the repository at this point in the history
feat: address book
  • Loading branch information
rolznz authored May 12, 2024
2 parents e6d3f95 + 90148a5 commit 22b987f
Show file tree
Hide file tree
Showing 30 changed files with 285 additions and 64 deletions.
2 changes: 1 addition & 1 deletion app.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"expo": {
"name": "Alby Mobile",
"slug": "alby-mobile",
"version": "1.1.0",
"version": "1.2.0",
"scheme": ["bitcoin", "lightning", "alby"],
"orientation": "portrait",
"icon": "./assets/icon.png",
Expand Down
2 changes: 1 addition & 1 deletion app/receive/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Receive } from "../../pages/Receive";
import { Receive } from "../../pages/receive/Receive";

export default function Page() {
return <Receive />;
Expand Down
2 changes: 1 addition & 1 deletion app/receive/success.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ReceiveSuccess } from "../../pages/ReceiveSuccess";
import { ReceiveSuccess } from "../../pages/receive/ReceiveSuccess";

export default function Page() {
return <ReceiveSuccess />;
Expand Down
5 changes: 5 additions & 0 deletions app/send/address-book.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { AddressBook } from "../../pages/send/AddressBook";

export default function Page() {
return <AddressBook />;
}
2 changes: 1 addition & 1 deletion app/send/confirm.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ConfirmPayment } from "../../pages/ConfirmPayment";
import { ConfirmPayment } from "../../pages/send/ConfirmPayment";

export default function Page() {
return <ConfirmPayment />;
Expand Down
2 changes: 1 addition & 1 deletion app/send/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Send } from "../../pages/Send";
import { Send } from "../../pages/send/Send";

export default function Page() {
return <Send />;
Expand Down
2 changes: 1 addition & 1 deletion app/send/lnurl-pay.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { LNURLPay } from "../../pages/LNURLPay";
import { LNURLPay } from "../../pages/send/LNURLPay";

export default function Page() {
return <LNURLPay />;
Expand Down
2 changes: 1 addition & 1 deletion app/send/success.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { PaymentSuccess } from "../../pages/PaymentSuccess";
import { PaymentSuccess } from "../../pages/send/PaymentSuccess";

export default function Page() {
return <PaymentSuccess />;
Expand Down
5 changes: 5 additions & 0 deletions app/settings/address-book/new.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { NewAddressBookEntry } from "../../../pages/settings/address-book/NewAddressBookEntry";

export default function Page() {
return <NewAddressBookEntry />;
}
5 changes: 0 additions & 5 deletions app/settings/lightning-address.js

This file was deleted.

5 changes: 0 additions & 5 deletions app/settings/wallet-connection.js

This file was deleted.

5 changes: 5 additions & 0 deletions app/settings/wallets/[id]/lightning-address.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { LightningAddress } from "../../../../pages/settings/wallets/LightningAddress";

export default function Page() {
return <LightningAddress />;
}
5 changes: 5 additions & 0 deletions app/settings/wallets/[id]/wallet-connection.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { WalletConnection } from "../../../../pages/settings/wallets/WalletConnection";

export default function Page() {
return <WalletConnection />;
}
9 changes: 9 additions & 0 deletions components/Icons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ import {
ArrowLeftRight,
PlusCircle,
Cog,
ClipboardPaste,
Keyboard,
BookUser,
} from "lucide-react-native";
import { cssInterop } from "nativewind";

Expand Down Expand Up @@ -47,6 +50,9 @@ interopIcon(Settings2);
interopIcon(ArrowLeftRight);
interopIcon(PlusCircle);
interopIcon(Cog);
interopIcon(ClipboardPaste);
interopIcon(Keyboard);
interopIcon(BookUser);

export {
AlertCircle,
Expand All @@ -65,4 +71,7 @@ export {
ArrowLeftRight,
PlusCircle,
Cog,
ClipboardPaste,
Keyboard,
BookUser,
};
44 changes: 26 additions & 18 deletions components/ToastConfig.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { View } from "react-native";
import { CheckCircle, XCircle } from "./Icons";
import { Link } from "expo-router";
import { Button } from "./ui/button";
import { useAppStore } from "~/lib/state/appStore";

export const toastConfig: ToastConfig = {
success: ({ text1, text2 }) => (
Expand Down Expand Up @@ -39,22 +40,29 @@ export const toastConfig: ToastConfig = {
</Card>
</View>
),
connectionError: ({ text1, text2, hide }) => (
<View className="w-full p-3">
<Card className="w-full">
<CardHeader>
<CardTitle>
<XCircle className="text-primary" width={20} height={20} /> {text1}
</CardTitle>
</CardHeader>
<CardContent className="p-4flex flex-row justify-end">
<Link href="/settings/wallet-connection" asChild>
<Button>
<Text>Update Wallet Connection</Text>
</Button>
</Link>
</CardContent>
</Card>
</View>
),
connectionError: ({ text1, text2, hide }) => {
const selectedWalletId = useAppStore((store) => store.selectedWalletId);
return (
<View className="w-full p-3">
<Card className="w-full">
<CardHeader>
<CardTitle>
<XCircle className="text-primary" width={20} height={20} />{" "}
{text1}
</CardTitle>
</CardHeader>
<CardContent className="p-4flex flex-row justify-end">
<Link
href={`/settings/wallets/${selectedWalletId}/wallet-connection`}
asChild
>
<Button>
<Text>Update Wallet Connection</Text>
</Button>
</Link>
</CardContent>
</Card>
</View>
);
},
};
43 changes: 41 additions & 2 deletions lib/state/appStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,26 @@ import { create } from "zustand";
import { NWCClient, Nip47Capability } from "@getalby/sdk/dist/NWCClient";
import { nwc } from "@getalby/sdk";
import { secureStorage } from "lib/secureStorage";
import { NewAddressBookEntry } from "~/pages/settings/address-book/NewAddressBookEntry";

interface AppState {
readonly nwcClient: NWCClient | undefined;
readonly fiatCurrency: string;
readonly selectedWalletId: number;
readonly wallets: Wallet[];
readonly addressBookEntries: AddressBookEntry[];
setNWCClient: (nwcClient: NWCClient | undefined) => void;
setNostrWalletConnectUrl(nostrWalletConnectUrl: string): void;
removeNostrWalletConnectUrl(): void;
updateCurrentWallet(wallet: Partial<Wallet>): void;
setFiatCurrency(fiatCurrency: string): void;
setSelectedWalletId(walletId: number): void;
addWallet(wallet: Wallet): void;
addAddressBookEntry(entry: AddressBookEntry): void;
}

const walletKeyPrefix = "wallet";
const addressBookEntryKeyPrefix = "addressBookEntry";
const selectedWalletIdKey = "selectedWalletId";
const fiatCurrencyKey = "fiatCurrency";

Expand All @@ -28,21 +32,30 @@ type Wallet = {
nwcCapabilities?: Nip47Capability[];
};

type AddressBookEntry = {
name?: string;
lightningAddress?: string;
};

const getWalletKey = (walletId: number) => {
return walletKeyPrefix + walletId;
};

const getAddressBookEntryKey = (addressBookEntryId: number) => {
return addressBookEntryKeyPrefix + addressBookEntryId;
};

function loadWallets(): Wallet[] {
// TODO: remove after a while - migrates from old single-wallet format
/////////////////////////////
const oldNostrWalletConnectUrlKey = "nostrWalletConnectUrl";
const oldNostrWalletConnectUrl = secureStorage.getItem(
oldNostrWalletConnectUrlKey
);
const oldLightningAddressKey = "lightningAddressKey";
const oldLightningAddressKey = "lightningAddress";
const oldLightningAddress = secureStorage.getItem(oldLightningAddressKey);

const oldNwcCapabilitiesKey = "nwcCapabilitiesKey";
const oldNwcCapabilitiesKey = "nwcCapabilities";
const oldNwcCapabilities = secureStorage.getItem(oldNwcCapabilitiesKey);
if (oldNostrWalletConnectUrl) {
const wallet: Wallet = {
Expand Down Expand Up @@ -71,6 +84,20 @@ function loadWallets(): Wallet[] {
return wallets;
}

function loadAddressBookEntries(): AddressBookEntry[] {
const addressBookEntries: AddressBookEntry[] = [];
for (let i = 0; ; i++) {
const addressBookEntryJSON = secureStorage.getItem(
getAddressBookEntryKey(i)
);
if (!addressBookEntryJSON) {
break;
}
addressBookEntries.push(JSON.parse(addressBookEntryJSON));
}
return addressBookEntries;
}

export const useAppStore = create<AppState>()((set, get) => {
const updateCurrentWallet = (walletUpdate: Partial<Wallet>) => {
const selectedWalletId = get().selectedWalletId;
Expand All @@ -95,6 +122,7 @@ export const useAppStore = create<AppState>()((set, get) => {
);
const initialWallets = loadWallets();
return {
addressBookEntries: loadAddressBookEntries(),
wallets: initialWallets,
nwcClient: getNWCClient(initialSelectedWalletId),
fiatCurrency: secureStorage.getItem(fiatCurrencyKey) || "",
Expand Down Expand Up @@ -134,6 +162,17 @@ export const useAppStore = create<AppState>()((set, get) => {
nwcClient: undefined,
});
},
addAddressBookEntry: (addressBookEntry: AddressBookEntry) => {
const currentAddressBookEntries = get().addressBookEntries;
const newAddressBookEntryId = currentAddressBookEntries.length;
secureStorage.setItem(
getAddressBookEntryKey(newAddressBookEntryId),
JSON.stringify(addressBookEntry)
);
set({
addressBookEntries: [...currentAddressBookEntries, addressBookEntry],
});
},
};
});

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "alby-mobile",
"version": "1.1.0",
"version": "1.2.0",
"main": "expo-router/entry",
"scripts": {
"start": "expo start",
Expand Down
5 changes: 4 additions & 1 deletion pages/Home.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
import React from "react";
import { useBalance } from "hooks/useBalance";
import { useAppStore } from "lib/state/appStore";
import { WalletConnection } from "pages/settings/WalletConnection";
import { WalletConnection } from "~/pages/settings/wallets/WalletConnection";
import { useTransactions } from "hooks/useTransactions";
import { Link, Stack, router, useFocusEffect } from "expo-router";
import dayjs from "dayjs";
Expand Down Expand Up @@ -55,6 +55,9 @@ export function Home() {
}, [allTransactions, transactions, refreshingTransactions]);

const onRefresh = React.useCallback(() => {
if (refreshingTransactions) {
return;
}
(async () => {
setRefreshingTransactions(true);
setPage(1);
Expand Down
11 changes: 6 additions & 5 deletions pages/Transaction.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
import { Nip47Transaction } from "@getalby/sdk/dist/NWCClient";
import dayjs from "dayjs";
import { Stack, useLocalSearchParams } from "expo-router";
import { Scroll } from "lucide-react-native";
import React from "react";
import { ScrollView, View } from "react-native";
import { CheckCircle, MoveDownLeft } from "~/components/Icons";
import { Separator } from "~/components/ui/separator";
import { View } from "react-native";
import { CheckCircle } from "~/components/Icons";
import { Text } from "~/components/ui/text";
import { useGetFiatAmount } from "~/hooks/useGetFiatAmount";
import { cn } from "~/lib/utils";
Expand Down Expand Up @@ -67,7 +65,10 @@ export function Transaction() {
title="Payment Hash"
content={transaction.payment_hash}
/>
<TransactionDetailRow title="Preimage" content={transaction.preimage} />
<TransactionDetailRow
title="Preimage"
content={transaction.preimage}
/>
</View>
</View>
</View>
Expand Down
5 changes: 4 additions & 1 deletion pages/Receive.tsx → pages/receive/Receive.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,10 @@ export function Receive() {
<Text className="text-2xl max-w-64 text-center">
Receive Quickly with a Lightning Address
</Text>
<Link href="/settings/lightning-address" asChild>
<Link
href={`/settings/wallets/${selectedWalletId}/lightning-address`}
asChild
>
<Button className="touch-none">
<Text className="text-background">Set Lightning Address</Text>
</Button>
Expand Down
File renamed without changes.
62 changes: 62 additions & 0 deletions pages/send/AddressBook.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { Link, Stack, router } from "expo-router";
import { Pressable, View } from "react-native";
import { PlusCircle } from "~/components/Icons";

import {
Card,
CardDescription,
CardHeader,
CardTitle,
} from "~/components/ui/card";
import { Text } from "~/components/ui/text";
import { useAppStore } from "~/lib/state/appStore";

export function AddressBook() {
const addressBookEntries = useAppStore((store) => store.addressBookEntries);
return (
<View className="flex-1 flex flex-col p-3 gap-3">
<Stack.Screen
options={{
title: "Address Book",
}}
/>
{addressBookEntries.map((addressBookEntry, index) => (
<Pressable
key={index}
onPress={() => {
router.dismissAll();
router.navigate({
pathname: "/send",
params: {
url: addressBookEntry.lightningAddress,
},
});
}}
>
<Card className="w-full">
<CardHeader className="w-full">
<CardTitle>
{addressBookEntry.name || addressBookEntry.lightningAddress}
</CardTitle>
<CardDescription>
{addressBookEntry.lightningAddress}
</CardDescription>
</CardHeader>
</Card>
</Pressable>
))}
<Link href="/settings/address-book/new" asChild>
<Pressable>
<Card className="w-full">
<CardHeader className="w-full">
<View className="flex flex-row items-center gap-2">
<PlusCircle className="text-primary" />
<Text className="font-bold">Add Address</Text>
</View>
</CardHeader>
</Card>
</Pressable>
</Link>
</View>
);
}
Loading

0 comments on commit 22b987f

Please sign in to comment.