Skip to content

Commit

Permalink
Merge pull request #326 from snake-eaterr/debit-improvements
Browse files Browse the repository at this point in the history
ndebit discoverable checkbox
  • Loading branch information
snake-eaterr authored Oct 6, 2024
2 parents 0213b9e + f8a4cba commit e2390da
Show file tree
Hide file tree
Showing 9 changed files with 277 additions and 98 deletions.
27 changes: 27 additions & 0 deletions src/Api/bridge/autogenerated/ts/http_client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,17 @@ export default (params: ClientParams) => ({
}
return { status: 'ERROR', reason: 'invalid response' }
},
UpdateMappingNdebit: async (request: Types.UpdateMappingNdebitRequest): Promise<ResultError | ({ status: 'OK' })> => {
const auth = await params.retrieveNostrAuth()
if (auth === null) throw new Error('retrieveNostrAuth() returned null')
let finalRoute = '/api/v1/noffer/update/ndebit'
const { data } = await axios.post(params.baseUrl + finalRoute, request, { headers: { 'authorization': auth } })
if (data.status === 'ERROR' && typeof data.reason === 'string') return data
if (data.status === 'OK') {
return data
}
return { status: 'ERROR', reason: 'invalid response' }
},
HandleLnurlPay: async (query: Types.HandleLnurlPay_Query): Promise<ResultError | ({ status: 'OK' }& Types.HandleLnurlPayResponse)> => {
const auth = await params.retrieveGuestAuth()
if (auth === null) throw new Error('retrieveGuestAuth() returned null')
Expand Down Expand Up @@ -89,4 +100,20 @@ export default (params: ClientParams) => ({
}
return { status: 'ERROR', reason: 'invalid response' }
},
HandleNip05Info: async (query: Types.HandleNip05Info_Query): Promise<ResultError | ({ status: 'OK' }& Types.nip05Names)> => {
const auth = await params.retrieveGuestAuth()
if (auth === null) throw new Error('retrieveGuestAuth() returned null')
let finalRoute = '/.well-known/nostr.json'
const q = (new URLSearchParams(query)).toString()
finalRoute = finalRoute + (q === '' ? '' : '?' + q)
const { data } = await axios.get(params.baseUrl + finalRoute, { headers: { 'authorization': auth } })
if (data.status === 'ERROR' && typeof data.reason === 'string') return data
if (data.status === 'OK') {
const result = data
if(!params.checkResult) return { status: 'OK', ...result }
const error = Types.nip05NamesValidate(result)
if (error === null) { return { status: 'OK', ...result } } else return { status: 'ERROR', reason: error.message }
}
return { status: 'ERROR', reason: 'invalid response' }
},
})
248 changes: 161 additions & 87 deletions src/Api/bridge/autogenerated/ts/types.ts

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions src/Api/bridge/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,8 @@ export default class Handler {
async GetOrCreateNofferName({ noffer, k1 }: { noffer: string, k1?: string }) {
return this.bridgeHttp.GetOrCreateNofferName({ k1, noffer });
}

async UpdateMappingNdebit({ ndebit }: { ndebit?: string }) {
return this.bridgeHttp.UpdateMappingNdebit({ ndebit })
}
}
33 changes: 26 additions & 7 deletions src/Pages/LinkedApp/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import Checkbox from "../../Components/Checkbox";
import { formatNumberWithCommas } from "../../utils/numbers";
import { useIonRouter } from "@ionic/react";
import Toast from "../../Components/Toast";
import { flipSourceNdebitDiscoverable } from "../../State/Slices/paySourcesSlice";

type StateDebitAuth = DebitAuthorization & { source: SpendFrom, domainName?: string, avatarUrl?: string }

Expand All @@ -39,7 +40,9 @@ export const LinkedApp = () => {
const [selectedSource, setSelectedSource] = useState(nostrSpends[0]);
const [hasNoDebits, setHasNoDebits] = useState(false)

const [isPubliclyAvailable, setIsPubliclyAvailable] = useState(false);
const [isPubliclyAvailable, setIsPubliclyAvailable] = useState(paySources.sources[selectedSource?.id]?.isNdebitDiscoverable || false);

const [lnAddress, setLnAddress] = useState("")

const [isShowingBans, setIsShowingBans] = useState(false);

Expand All @@ -52,7 +55,15 @@ export const LinkedApp = () => {
}, [nostrSpends, router]);




const fetchAuths = useCallback(() => {
if (!selectedSource) return;
const counterpartPaySource = paySources.sources[selectedSource.id]
if (counterpartPaySource) {
setLnAddress(counterpartPaySource.vanityName || "")
setIsPubliclyAvailable(!!counterpartPaySource.isNdebitDiscoverable)
}
const { pubkey, relays } = parseNprofile(selectedSource.pasteField)
getNostrClient({ pubkey, relays }, selectedSource.keys).then(c => {
c.GetDebitAuthorizations().then(res => {
Expand Down Expand Up @@ -85,7 +96,6 @@ export const LinkedApp = () => {
const cardsToRender = useMemo(() => {
const debitsToShow: StateDebitAuth[] = isShowingBans ? debitAuthorizations.debitAuthsBanned : debitAuthorizations.debitAuths
return debitsToShow.map((debitAuth, index) => {
console.log({debitAuth})
const npub = nip19.npubEncode(debitAuth.npub);
const substringedNpub = `${npub.substring(0, 20)}...${npub.substring(npub.length - 20, npub.length)}`;

Expand Down Expand Up @@ -159,10 +169,19 @@ export const LinkedApp = () => {
})
}, [debitAuthorizations, dispatch, isShowingBans])

const counterpartPaySource = paySources.sources[selectedSource.id] || null;


const handleFlipPubliclyDiscoverable = (checked: boolean) => {
if (!selectedSource) return;
const counterpartPaySource = paySources.sources[selectedSource.id]
if (counterpartPaySource) {
dispatch(flipSourceNdebitDiscoverable({ ...counterpartPaySource, isNdebitDiscoverable: checked }));
setIsPubliclyAvailable(checked)
}
}

return (
<div className={styles["wrapper"]}>
<div className={styles["wrapper"]} key={selectedSource.id}>
<div className={styles["container"]}>

<div className={styles["page-header"]}>Linked Apps</div>
Expand Down Expand Up @@ -212,15 +231,15 @@ export const LinkedApp = () => {
{selectedSource.ndebit}
</span>
{
(counterpartPaySource && counterpartPaySource.vanityName)
lnAddress
&&
<>
<div className={styles["checkbox-container"]} style={{ marginTop: "12px" }}>
<span className={styles["label"]}>Make publicly discoverable via Lightning Address:</span>
<Checkbox id="publicly-available" state={isPubliclyAvailable} setState={(e) => setIsPubliclyAvailable(e.target.checked)} />
<Checkbox id="publicly-available" state={isPubliclyAvailable} setState={(e) => handleFlipPubliclyDiscoverable(e.target.checked)} />
</div>
<div className={styles["checkbox-container"]}>
<span className={styles["ln-address"]}>&#40;{counterpartPaySource.vanityName}&#41;</span>
<span className={styles["ln-address"]}>&#40;{lnAddress}&#41;</span>
</div>
</>
}
Expand Down
7 changes: 6 additions & 1 deletion src/State/Slices/paySourcesSlice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,11 @@ const paySourcesSlice = createSlice({
return acc
}, [] as string[]);
update(state);
},
flipSourceNdebitDiscoverable: (state, action: PayloadAction<PayTo>) => {
state.sources[action.payload.id] = action.payload
update(state)
return state;
}
},
extraReducers: (builder) => {
Expand All @@ -239,5 +244,5 @@ const paySourcesSlice = createSlice({
}
});

export const { addPaySources, editPaySources, deletePaySources, setPaySources, fixPayDuplicates } = paySourcesSlice.actions;
export const { addPaySources, editPaySources, deletePaySources, setPaySources, fixPayDuplicates, flipSourceNdebitDiscoverable } = paySourcesSlice.actions;
export default paySourcesSlice.reducer;
5 changes: 3 additions & 2 deletions src/State/backupMiddleware.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { addListener, AnyAction, TypedAddListener, createAction, createListenerMiddleware, ListenerEffectAPI, TaskAbortError, ThunkDispatch, removeListener, TypedRemoveListener, TypedStartListening } from "@reduxjs/toolkit";
import { addPaySources, deletePaySources, editPaySources, PaySourceRecord, setPaySources } from "./Slices/paySourcesSlice";
import { addPaySources, deletePaySources, editPaySources, flipSourceNdebitDiscoverable, PaySourceRecord, setPaySources } from "./Slices/paySourcesSlice";
import { setLatestLnurlOperation } from "./Slices/HistorySlice";
import { addSpendSources, deleteSpendSources, editSpendSources, setSpendSources, SpendSourceRecord } from "./Slices/spendSourcesSlice";
import { fetchRemoteBackup, saveChangelog, saveRemoteBackup, subscribeToRemoteChangelogs } from "../helpers/remoteBackups";
Expand Down Expand Up @@ -428,7 +428,8 @@ export const backupMiddleware = {
deletePaySources.match(action) ||
setPaySources.match(action) ||
setLatestLnurlOperation.match(action) ||
setPrefs.match(action)
setPrefs.match(action) ||
flipSourceNdebitDiscoverable.match(action)
)
);
},
Expand Down
47 changes: 47 additions & 0 deletions src/State/ndebitDiscoverableMiddleware.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { createListenerMiddleware, ListenerEffectAPI, PayloadAction, TypedStartListening } from "@reduxjs/toolkit";
import { flipSourceNdebitDiscoverable } from "./Slices/paySourcesSlice";
import { AppDispatch, State } from "./store";
import { PayTo } from "../globalTypes";
import Bridge from "../Api/bridge";
import { Buffer } from "buffer";

import { finalizeEvent, nip98 } from 'nostr-tools'
const { getToken } = nip98






export const ndebitDiscoverableListener = {
actionCreator: flipSourceNdebitDiscoverable,
effect: async (action: PayloadAction<PayTo>, listenerApi: ListenerEffectAPI<State, AppDispatch>) => {
const paySource = action.payload;
const counterpartSpendSource = listenerApi.getState().spendSource.sources[paySource.id];
if (paySource.bridgeUrl) {
if (paySource.isNdebitDiscoverable && counterpartSpendSource.ndebit) {
const payload = { ndebit: counterpartSpendSource.ndebit }
const nostrHeader = await getToken(`${paySource.bridgeUrl}/api/v1/noffer/update/ndebit`, "POST", e => finalizeEvent(e, Buffer.from(paySource.keys.privateKey, 'hex')), true, payload)
const bridgeHandler = new Bridge(paySource.bridgeUrl, nostrHeader);
const res = await bridgeHandler.UpdateMappingNdebit(payload)
if (res.status !== "OK") {
throw new Error(res.reason);
}
} else if (!paySource.isNdebitDiscoverable) {
const payload = {}
const nostrHeader = await getToken(`${paySource.bridgeUrl}/api/v1/noffer/update/ndebit`, "POST", e => finalizeEvent(e, Buffer.from(paySource.keys.privateKey, 'hex')), true, payload)
const bridgeHandler = new Bridge(paySource.bridgeUrl, nostrHeader);
const res = await bridgeHandler.UpdateMappingNdebit(payload)
if (res.status !== "OK") {
throw new Error(res.reason);
}
}
}


}
}

export const ndebitMiddleware = createListenerMiddleware()
const typedStartListening = ndebitMiddleware.startListening as TypedStartListening<State, AppDispatch>
typedStartListening(ndebitDiscoverableListener);
3 changes: 2 additions & 1 deletion src/State/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { backup } from './backupMiddleware';
import { BackupAction } from './types';
import { bridgeMiddleware } from './bridgeMiddleware';
import modalsSlice from './Slices/modalsSlice';
import { ndebitMiddleware } from './ndebitDiscoverableMiddleware';

export const syncRedux = createAction('SYNC_REDUX');

Expand Down Expand Up @@ -46,7 +47,7 @@ export const reducer = combineReducers({
const store = configureStore({
reducer: reducer,
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware().prepend(backup.middleware, bridgeMiddleware.middleware),
getDefaultMiddleware().prepend(backup.middleware, bridgeMiddleware.middleware, ndebitMiddleware.middleware),
});
export type State = ReturnType<typeof store.getState>
export type AppDispatch = typeof store.dispatch
Expand Down
1 change: 1 addition & 0 deletions src/globalTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ export interface PayTo {
pubSource?: boolean,
keys: NostrKeyPair
bridgeUrl?: string
isNdebitDiscoverable?: boolean
}

export interface FiatCurrency {
Expand Down

0 comments on commit e2390da

Please sign in to comment.