Connecting mobile apps to the MultiversX's xPortal mobile wallet.
npm install react-native-xportal
or
yarn add react-native-xportal
The library needs @react-native-async-storage/async-storage
and react-native-get-random-values
to work properly. Make sure you install them:
npm install @react-native-async-storage/async-storage react-native-get-random-values
or;
yarn add @react-native-async-storage/async-storage react-native-get-random-values
The library works as a react-native substitute for mx-sdk-dapp, it helps mobile apps connect and interact with the XPortal wallet, including providing the necessary account information (balance, tokens, address etc) and signing transactions, messages or custom requests, thus abstracing all the processes of interacting with users' wallets. On connect, sign transaction or other actions, XPortal app will automatically be opened through deeplinking to complete the intended action.
The library has 2 main modules: core
and UI
. The core
modules gives you the functions to connect, sign transactions and other so that you can call them anywhere you need. The UI
modules exports buttons for ease of use, they also use the core
module under the hood.
Note: This library has all the basic functionalities for interacting with the XPortal Wallet. New functionalities can be added - if you want to contribute, please see the Contributing section.
The library needs to be initalized first in order to work, see example below.
import { XPortal } from 'react-native-xportal';
const callbacks = {
onClientLogin: async () => {
console.log('on login');
},
onClientLogout: async () => {
console.log('on logout');
},
onClientEvent: async (event: any) => {
console.log('event -> ', event);
},
};
try {
await XPortal.initialize({
chainId: 'd',
projectId: '<wallet connect project ID>',
metadata: {
description: 'Connect with X',
url: '<your website>',
icons: ['<https://img.com/linkToIcon.png>'],
name: '<name>',
},
callbacks,
});
} catch (error) {
console.log(error);
}
You need to have a WalletConnect project ID. To get one see: https://cloud.walletconnect.com/app. Also, make sure to have valid data in your metadata key, otherwise the XPortal wallet will show a "Unexpected Error" when redirecting to it for login.
import { XPortal } from 'react-native-xportal';
try {
await XPortal.login();
} catch (error: any) {
throw new Error(error.message);
}
This will connect your app to user's XPortal app and his account.
import { XPortal } from 'react-native-xportal';
try {
await XPortal.logout();
} catch (error: any) {
throw new Error(error.message);
}
Disconnects your app from XPortal, cleaning the connection.
import { XPortal } from 'react-native-xportal';
try {
const data = {transactions: [{
value: '1000000000000',
receiver:
'erd1ju59m5rcrulg0h87ysed5acrz08xa4pkzts0hrzy2lau3ak3ne0sauhxgx',
sender:
'erd1ju59m5rcrulg0h87ysed5acrz08xa4pkzts0hrzy2lau3ak3ne0sauhxgx',
gasPrice: 1000000000,
gasLimit: 70000,
data: 'Zm9vZCBmb3IgY2F0cw==',
chainId: 'D',
nonce: 1,
version: 1,
}],
// minGasLimit: 50_000 (optional)
};
const transactions = await XPortal.signTransactions(data);
const signature = transactions[0].getSignature().toString('hex');
} catch (error: any) {
throw new Error(error.message);
}
Transactions need to be in an array, thus being able to tolerate one or many transaction for signing.
Make sure all the transactions have a chainId
and the proper nonce
value.
Transactions will be sent to XPortal where the user can sign them an return them back to your app. This function DOES NOT send the transaction over the MultiversX's blockchain - a better approach would be to send the signed transaction to your back-end and let it handle the broadcast and other changes that the trasanction imposes on your system. If broadcasting the transaction functionality is needed, it will be added eventually. Please see Contributing if you want to add this functionality.
import { XPortal } from 'react-native-xportal';
const signedMessage = await XPortal.signMessage({message: 'Passion'});
const signature = signedMessage.getSignature().toString('hex');
Like signing transactions, signMessage
signes a message and returns it back signed.
import { XPortal } from 'react-native-xportal';
try {
const response = await XPortal.sendCustomRequest({
request: { method: WalletConnectOptionalMethodsEnum.CANCEL_ACTION, params: { action: 'string here' }}
});
} (error: any) {
throw new Error(error.message);
}
Send a custom request to XPortal, method and params need to specified in relation to your needs.
import { XPortal } from 'react-native-xportal';
try {
const isActive = await XPortal.ping();
} (error: any) {
throw new Error(error.message);
}
Returns a Boolean
to reflect the state of the connection with the XPortal.
import { XPortal } from 'react-native-xportal';
try {
const accountData = await XPortal.refreshAccountData();
} (error: any) {
throw new Error(error.message);
}
Provides the ability to manually refresh the account data stored if there have been changes to user's wallet outside of your app.
import { XPortal } from 'react-native-xportal';
try {
const state = await XPortal.watchTransaction({
transactionHash: '8d78c007750e3c137943e4de7a7df5702bb11ae6541a4864670b5cf4420cf8e5',
});
} (error: any) {
throw new Error(error.message);
}
Provides the ability to watch any transaction's status after it was sent to the MultiversX blockchain.
import { XPortal } from 'react-native-xportal';
const address = XPortal.getWalletAddress();
const isConnected = XPortal.isConnected();
const account = XPortal.getFullAccountInfo();
const tokens = XPortal.getAccountTokensList();
const balance = XPortal.getAccountBalance();
Provides different information about the state of the account.
You can see below an example with all the UI components currently provided.
import {
XPortalLogin,
XPortalLogout,
XPortalSignMessage,
XPortalSignTx,
} from 'react-native-xportal';
<XPortalLogin />
<XPortalLogout style={{marginTop: 20}} />
<XPortalSignTx
style={{marginTop: 20}}
transactions={[{
value: '1000000000000',
receiver:
'erd1ju59m5rcrulg0h87ysed5acrz08xa4pkzts0hrzy2lau3ak3ne0sauhxgx',
sender:
'erd1ju59m5rcrulg0h87ysed5acrz08xa4pkzts0hrzy2lau3ak3ne0sauhxgx',
gasPrice: 1000000000,
gasLimit: 70000,
data: 'Zm9vZCBmb3IgY2F0cw==',
chainId: 'D',
version: 1,
},
]}
callback={(signedTx) => doStuff(signedTx)}
/>
<XPortalSignMessage
style={{marginTop: 20}}
message="Passion"
callback={(signedMessage) => doStuff(signedMessage)}
content={<View> <Text>This is a custom content inside the button</Text> </View>}
/>
All buttons can be styled and the content inside can be changed with the content
prop.
Prop Name | Type | Available for | Description |
---|---|---|---|
content | React.ReactElement |
All components | Replaces the content of the button. |
style | StyleProp<ViewStyle> |
All components | Styles for the button |
callback | (res) => void |
XPortalSignTx , XPortalSignMessage |
Callback function to get back the result |
transaction | SimpleTransactionType[] |
XPortalSignTx |
Transaction to be signed |
message | string |
XPortalSignMessage |
The message to be signed |
Here are some features that need to be implemented:
- Tests
- Stage-linter
- Signed Transaction log (if it is needed)
- Transaction broadcast (if it is needed)
- Husky for commit lint
For more, see the Open Issues for a list of proposed features and known issues. Check out Contributing below to get started.
Contributions are what make the open source community such an amazing place to learn, inspire, and create. Any contributions you make are greatly appreciated.
One can contribute by creating pull requests, or by opening issues for discovered bugs or desired features.
- Fork the Project
- Create your Feature Branch (
git checkout -b feature/AmazingFeature
) - Commit your Changes (
git commit -m 'Add some AmazingFeature'
) - Push to the Branch (
git push origin feature/AmazingFeature
) - Open a Pull Request
This project is licensed under the MIT License - see the LICENSE file for details.