A React Native JS library to enable easy communication with TAPSIGNER™ and SATSCARD™.
-==[Request card development samples here]==-
See the python library by Coinkite for protocol specifications.
yarn add coinkite-tap-protocol
This library uses a few node core modules like secp256k1, buffer, crypto etc. which react native doesn't support because they probably use C++ code bundled with the Node JS binary, not Javascript.
We suggest using rn-nodify to enable using node core modules after yarn add coinkite-tap-protocol
rn-nodify needs stream-browserify for browser support.
metro.config.js
...
resolver: {
extraNodeModules: {
stream: require.resolve('stream-browserify'),
},
},
transformer: {
...
},
...
react-native-nfc-manager is used for the NFC communications with the cards. Please refer to their docs for nfc integration.
-
add the post install script in your package.json
"postinstall": "rn-nodeify --install fs,dgram,process,path,console,crypto --hack"
-
install the required modules
yarn add coinkite-tap-protocol rn-nodify stream-browserify react-native-nfc-manager
-
update metro config resolver
extraNodeModules: {
stream: require.resolve('stream-browserify'),
}
- install respoective cocopod dependencies
cd ios && pod install
Create a Protocol calss to interact with the TAPSIGNER/SATSCARD.
import { CKTapCard } from 'cktap-protocol-react-native';
.
.
.
const card: CKTapCard = useRef(new CKTapCard()).current;
The library provides a wrapper to initialte NFC and make batch calls to the TAPSIGNER/SATSCARD with a single NFC scan.
const cardStatus = await card.nfcWrapper(async () => {
// interact with the card here
return card.first_look(); // scans the card for basic details and initialises with it
});
You can also batch commands in a single NFC scan
const initiatedCard = await card.nfcWrapper(async () => {
const cardStatus = await card.first_look();
const isCardLegit = await card.certificate_check();
if (isCardLegit) {
// run the setup command just once
await card.setup(cvc); // setup the card with the CVC at the back of the card (don't forget to prompt the user to change it later)
}
return card;
});
Fetch the xpub, derivation path and fingerprint post setup
const initiatedCard = await card.nfcWrapper(async () => {
const cardStatus = await card.first_look();
if (status.path) {
const xpub = await card.get_xpub(cvc);
const fingerprint = await card.get_xfp(cvc);
return { xpub, derivationPath: cardStatus.path, fingerprint: fingerprint.toString('hex') };
} else {
await card.setup(cvc);
const cardStatus = await card.first_look();
const xpub = await card.get_xpub(cvc);
const fingerprint = await card.get_xfp(cvc);
return { xpub, derivationPath: cardStatus.path, fingerprint: fingerprint.toString('hex') };
}
});
- Make sure you call the following command on android once the interactions with the card is completed. This is specifically done in android as we do not end the nfc after the wrapper has executed the commands but which is not the case with iOS. This behaviour is different for different platforms since the NFC interaction is blocking in iOS (system dialog) and non-blocking in android. Hence the user can manually add NFC dialogs/interactions in case of android when the communication with the card is done (optionally).
// Android-only
await card.endNfcSession(); // either call is on component unmount or post card.nfcWrapper
NOTE
- Place the card for the NFC scan before card.nfcWrapper is called. There is no need to remove the card until the wrapper completes the callback.
- iOS has it's own system NFC interaction to let the user know that the NFC is active.
- Android has no interaction as such. You can use your own modal/interaction which can open and close before/after the callback to card.nfcWrapper.
- Demo app with detailed usage of the library.
Run test suits for the library with
yarn test
Lint the library with
yarn lint