-
Notifications
You must be signed in to change notification settings - Fork 3
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
Pin support (LUD-21) #33
Conversation
src/hooks/useNfc.ts
Outdated
@@ -49,7 +70,7 @@ export const useNfc = () => { | |||
}, []); | |||
|
|||
const readingNfcLoop = useCallback( | |||
async (pr: string) => { | |||
async (pr: string, amount: number) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had to pass the amount into this function to check if pin is required.
It is also needed for the commented out part, the lnurlp request as far as I understand. Was there a reason why it is commented out? Are there any bugs or is it a bad idea to add this parameter to the function?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The LNURLp was commented as it require some additional work. We could do that in another PR :)
Adding the amount
is okay.
if (debitCardData?.status === "OK" && !error) { | ||
setIsNfcActionSuccess(true); | ||
} else { | ||
if (debitCardData?.status === "ERROR" && !error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the pin is wrong the response is in the debitCardData object not the error object. Is that a wrong implementation on my side? Should the server send another status then 200? I haven't seen a specification for that in the LUD-3.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's probably a mis-implementation on our side. You can keep the code like this for the moment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Additionally, there is quite a few of lint issues.
Please run npm run lint
and fix the errors you see.
package.json
Outdated
@@ -47,6 +47,7 @@ | |||
"react-dom": "18.2.0", | |||
"react-i18next": "13.2.2", | |||
"react-native": "0.73.2", | |||
"react-native-animated-bottom-drawer": "^0.0.23", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For security reasons, we keep the version fixed like this:
"react-native-animated-bottom-drawer": "^0.0.23", | |
"react-native-animated-bottom-drawer": "0.0.23", |
Please do npm install
again after changing
package.json
Outdated
@@ -58,6 +59,7 @@ | |||
"react-native-dotenv": "3.4.9", | |||
"react-native-linear-gradient": "2.8.3", | |||
"react-native-nfc-manager": "3.14.11", | |||
"react-native-pin-view": "^3.0.3", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For security reasons, we keep the version fixed like this:
"react-native-pin-view": "^3.0.3", | |
"react-native-pin-view": "3.0.3", |
Please do npm install
again after changing
src/hooks/useNfc.ts
Outdated
@@ -49,7 +70,7 @@ export const useNfc = () => { | |||
}, []); | |||
|
|||
const readingNfcLoop = useCallback( | |||
async (pr: string) => { | |||
async (pr: string, amount: number) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The LNURLp was commented as it require some additional work. We could do that in another PR :)
Adding the amount
is okay.
src/hooks/useNfc.ts
Outdated
@@ -114,15 +135,31 @@ export const useNfc = () => { | |||
tag: "withdrawRequest"; | |||
callback: string; | |||
k1: string; | |||
pinLimit: number; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As pinLimit
is not always defined, you need to add a ?
as "possibly undefined"
pinLimit: number; | |
pinLimit?: number; |
}>(cardData); | ||
|
||
let pin = ""; | ||
if (cardDataResponse.pinLimit !== undefined) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Simplify it with:
if (cardDataResponse.pinLimit !== undefined) { | |
if (cardDataResponse.pinLimit) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was thinking that the pinLimit could be set to 0. But then one could argue that means it is "disabled" since the number in the pinLimit is the min amounted needed before asking the pin and the smallest possible number for that would be 1.
How should we implement it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Interesting. The doc says value must be a positive integer (including 0)
, but also to withdraw an amount equal to or greater [...]
.
But as we can't really withdraw 0 sat, I agree with you that 0 could means "disabled".
As this is not clear, you can keep it as cardDataResponse.pinLimit !== undefined
and ignore my initial comment.
if (debitCardData?.status === "OK" && !error) { | ||
setIsNfcActionSuccess(true); | ||
} else { | ||
if (debitCardData?.status === "ERROR" && !error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's probably a mis-implementation on our side. You can keep the code like this for the moment.
src/screens/Invoice/Invoice.tsx
Outdated
@@ -32,6 +32,8 @@ import { faBitcoin } from "@fortawesome/free-brands-svg-icons"; | |||
import axios from "axios"; | |||
import * as S from "./styled"; | |||
|
|||
import { PinPad } from "../PinPad"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please do the following:
- Move the PinPad component (folder) to
src/components
- Add
export { PinPad } from "./PinPad";
tosrc/components/index.ts
- Change this line to:
import { PinPad } from "../PinPad"; | |
import { PinPad } from "@components"; |
src/screens/PinPad/PinPad.tsx
Outdated
import { faDeleteLeft, faUnlock } from "@fortawesome/free-solid-svg-icons"; | ||
|
||
export const PinPad = (props) => { | ||
const pinView = useRef(null); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Above the component, you can add the following:
type PinViewFunctions = {
clearAll: () => void;
};
And change this line to
const pinView = useRef(null); | |
const pinView = useRef<PinViewFunctions>(null); |
src/screens/PinPad/PinPad.tsx
Outdated
import { Text, Icon } from "@components"; | ||
import { faDeleteLeft, faUnlock } from "@fortawesome/free-solid-svg-icons"; | ||
|
||
export const PinPad = (props) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You need to type the props, like we do on other components.
src/screens/PinPad/PinPad.tsx
Outdated
const styles = StyleSheet.create({ | ||
container: { | ||
backgroundColor: "rgba(0,0,0,0.5)", | ||
}, | ||
handleContainer: { | ||
backgroundColor: "transparent", | ||
}, | ||
pinPad: { | ||
backgroundColor: "transparent", | ||
alignItems: "center", | ||
flex: 1, | ||
}, | ||
pinPadTitle: { | ||
paddingTop: 48, | ||
paddingBottom: 24, | ||
color: "rgba(255,255,255,1)", | ||
fontSize: 48, | ||
}, | ||
whiteBorder: { | ||
borderWidth: 1, | ||
borderColor: "#FFF", | ||
}, | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We usually we styled-components
.
Can you try to migrate this to styled.ts
. Check other styled.ts
files in the repo to see how it works. It's pretty simple!
And it help to keep the component's logic files clean.
src/hooks/useNfc.ts
Outdated
const [ pinResolver, setPinResolver ] = useState({ resolve: undefined }) | ||
|
||
const setPin = (pin: string) => { | ||
if(pinResolver.resolve) { | ||
pinResolver.resolve(pin); | ||
} | ||
} | ||
|
||
const getPin = useCallback(async () => { | ||
const pinInputPromise = () => { | ||
let _pinResolver; | ||
return [ new Promise(( resolve ) => { | ||
_pinResolver = resolve | ||
}), _pinResolver] | ||
} | ||
|
||
const [ promise, resolve ] = pinInputPromise() | ||
setPinResolver({ resolve }) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can fix TS issues here by committing this
const [ pinResolver, setPinResolver ] = useState({ resolve: undefined }) | |
const setPin = (pin: string) => { | |
if(pinResolver.resolve) { | |
pinResolver.resolve(pin); | |
} | |
} | |
const getPin = useCallback(async () => { | |
const pinInputPromise = () => { | |
let _pinResolver; | |
return [ new Promise(( resolve ) => { | |
_pinResolver = resolve | |
}), _pinResolver] | |
} | |
const [ promise, resolve ] = pinInputPromise() | |
setPinResolver({ resolve }) | |
const [pinResolver, setPinResolver] = useState<{ | |
resolve: (v: string) => void; | |
}>(); | |
const setPin = (pin: string) => { | |
if (pinResolver?.resolve) { | |
pinResolver.resolve(pin); | |
} | |
}; | |
const getPin = useCallback(async () => { | |
const pinInputPromise = () => { | |
let _pinResolver; | |
return [ | |
new Promise<string>((resolve) => { | |
_pinResolver = resolve; | |
}), | |
_pinResolver | |
]; | |
}; | |
const [promise, resolve] = pinInputPromise(); | |
setPinResolver({ resolve } as unknown as { resolve: (v: string) => void }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had something like that but wasn't thinkin about casting first to unknown. Thanks 👍
src/components/PinPad/PinPad.tsx
Outdated
buttonViewStyle={S.PinViewStyles.whiteBorder} | ||
buttonTextStyle={{ color: "#FFF" }} | ||
onButtonPress={key => setButtonPressed(key)} | ||
customLeftButton={showRemoveButton ? <Icon icon={faDeleteLeft} size={36} color={"#FFF"} /> : undefined} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To fix the TS issue here, you need to replace this lin with:
customLeftButton={showRemoveButton ? <Icon icon={faDeleteLeft} size={36} color={"#FFF"} /> : undefined} | |
customLeftButton={showRemoveButton ? LeftButton : undefined} |
And add a LeftButton component below:
const LeftButton = () => <Icon icon={faDeleteLeft} size={36} color={"#FFF"} />;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had <LeftButton />, so that's how you do it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If I do it without <> it never appears
</S.PinPadTitle> | ||
<ReactNativePinView | ||
inputSize={32} | ||
ref={pinView} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To avoid a new TS issue here, add a // @ts-ignore
:
ref={pinView} | |
// @ts-ignore | |
ref={pinView} |
This PR implements the LUD-21 as specified here https://github.com/bitcoin-ring/luds/blob/withdraw-pin/21.md
This LUD has not been merged to as official LNURL LUD
Adds a pin pad that appears inside a bottom drawer to enter a 4 digit pin if the amount that has to be paid is bigger then the pinLimit value of the LNURLw response.