Am trying to integrate xrp pnp sdk into our webapp.
here’s the link from docs and I got two major concerns
- Hosted Xrp examples present on above docs page are actually throwing errors so wanted to know are they the latest one?
- I tried following exact commands from xrp integration github readme but got node_modules corrupt error so wanted to understand if that’s the latest repo and the correct one?
Though by making some changes I was able to make the auth work but can’t do further actions like getting user acc details or signing txns.
I think its related to rpc somewhere
sorry if am doing anything wrong so pls can someone guide me in how to resolve it?
all errors and steps mentioned in below
App.tsx
import { useEffect, useState } from "react";
import { Web3Auth, Web3AuthOptions } from "@web3auth/modal";
import {
CHAIN_NAMESPACES,
IProvider,
UX_MODE,
WEB3AUTH_NETWORK,
} from "@web3auth/base";
import { AuthAdapter } from "@web3auth/auth-adapter";
import { XrplPrivateKeyProvider } from "@web3auth/xrpl-provider";
import RPC from "./xrplRPC";
import { Web3AuthNoModal } from "@web3auth/no-modal";
import "./App.css";
const clientId =
"";
const chainConfig = {
chainNamespace: CHAIN_NAMESPACES.XRPL,
chainId: "0x2",
rpcTarget: "https://testnet.xrpl-labs.com/", // needed to change rpcs mentioned in docs becoz they were throwing errors connecting to them
wsTarget: "wss://testnet.xrpl-labs.com/",
ticker: "XRP",
tickerName: "XRPL",
displayName: "xrpl testnet",
blockExplorerUrl: "https://livenet.xrpl.org",
};
const privateKeyProvider = new XrplPrivateKeyProvider({
config: { chainConfig },
});
const web3AuthOptions: Web3AuthOptions = {
clientId,
web3AuthNetwork: WEB3AUTH_NETWORK.SAPPHIRE_DEVNET,
privateKeyProvider,
};
const web3auth = new Web3Auth(web3AuthOptions);
function App() {
const [provider, setProvider] = useState<IProvider | null>(null);
const [loggedIn, setLoggedIn] = useState(false);
useEffect(() => {
const init = async () => {
try {
// IMP START - SDK Initialization
await web3auth.initModal();
// IMP END - SDK Initialization
console.log("iniii", web3auth.provider);
setProvider(web3auth.provider);
if (web3auth.connected) {
setLoggedIn(true);
}
} catch (error) {
console.error(error);
}
};
init();
}, []);
const login = async () => {
if (!web3auth) {
uiConsole("web3auth not initialized yet");
return;
}
const web3authProvider = await web3auth.connect();
console.log("authh", web3authProvider);
setProvider(web3authProvider!);
setLoggedIn(true);
};
const authenticateUser = async () => {
if (!web3auth) {
uiConsole("web3auth not initialized yet");
return;
}
const idToken = await web3auth.authenticateUser();
uiConsole(idToken);
};
const getUserInfo = async () => {
if (!web3auth) {
uiConsole("web3auth not initialized yet");
return;
}
const user = await web3auth.getUserInfo();
uiConsole(user);
};
const logout = async () => {
if (!web3auth) {
uiConsole("web3auth not initialized yet");
return;
}
await web3auth.logout();
setProvider(null);
setLoggedIn(false);
};
const getAccounts = async () => {
const user = await web3auth.getUserInfo();
console.log(user);
try {
// I tried using xrplRPC file function here as well but not working so I pasted exact code here for your reference
//NOTE: unable to call .request() as its not provided in provider
//ERROR : App.tsx:562 Error JsonRpcError: Cannot read properties of undefined (reading 'call') at getJsonRpcError
const accounts = await privateKeyProvider.request({
method: "xrpl_getAccounts",
});
console.log(accounts);
if (accounts) {
const accInfo = (await privateKeyProvider.request({
method: "account_info",
params: [
{
account: accounts[0],
strict: true,
ledger_index: "current",
queue: true,
},
],
})) as Record<string, Record<string, string>>;
console.log("XRPL account info", accInfo);
// XRPL Account
const account = accInfo?.account_data?.Account;
// Balance
const balance = accInfo?.account_data?.Balance;
} else {
console.log("No accounts found, please report this issue.");
}
} catch (error) {
console.error("Error", error);
}
};
const getBalance = async () => {
if (!provider) {
uiConsole("provider not initialized yet");
return;
}
const rpc = new RPC(provider);
const balance = await rpc.getBalance();
uiConsole("Balance", balance);
};
const sendTransaction = async () => {
if (!provider) {
uiConsole("provider not initialized yet");
return;
}
const rpc = new RPC(provider);
const result = await rpc.signAndSendTransaction();
uiConsole(result);
};
const signMessage = async () => {
if (!provider) {
uiConsole("provider not initialized yet");
return;
}
const rpc = new RPC(provider);
const result = await rpc.signMessage();
uiConsole(result);
};
function uiConsole(...args: any[]): void {
const el = document.querySelector("#console>p");
if (el) {
el.innerHTML = JSON.stringify(args || {}, null, 2);
}
}
const loggedInView = (
<>
<div className="flex-container">
<div>
<button onClick={getUserInfo} className="card">
Get User Info
</button>
</div>
<div>
<button onClick={authenticateUser} className="card">
Get ID Token
</button>
</div>
<div>
<button onClick={getAccounts} className="card">
Get Accounts
</button>
</div>
<div>
<button onClick={getBalance} className="card">
Get Balance
</button>
</div>
<div>
<button onClick={signMessage} className="card">
Sign Message
</button>
</div>
<div>
<button onClick={sendTransaction} className="card">
Send Transaction
</button>
</div>
<div>
<button onClick={logout} className="card">
Log Out
</button>
</div>
</div>
<div id="console" style={{ whiteSpace: "pre-line" }}>
<p style={{ whiteSpace: "pre-line" }}></p>
</div>
</>
);
const unloggedInView = (
<button onClick={login} className="card">
Login
</button>
);
return (
<div className="container">
<h1 className="title">
<a
target="_blank"
href="https://web3auth.io/docs/sdk/pnp/web/modal"
rel="noreferrer"
>
Web3Auth{" "}
</a>
& React XRPL Example
</h1>
<div className="grid">{loggedIn ? loggedInView : unloggedInView}</div>
<footer className="footer">
<a
href="https://github.com/Web3Auth/web3auth-pnp-examples/tree/main/web-modal-sdk/blockchain-connection-examples/xrpl-modal-example"
target="_blank"
rel="noopener noreferrer"
>
Source code
</a>
<a href="https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2FWeb3Auth%2Fweb3auth-pnp-examples%2Ftree%2Fmain%2Fweb-modal-sdk%2Fblockchain-connection-examples%2Fxrpl-modal-example&project-name=w3a-xrpl-modal&repository-name=w3a-xrpl-modal">
<img src="https://vercel.com/button" alt="Deploy with Vercel" />
</a>
</footer>
</div>
);
}
export default App;
xrplRPC.ts
import { IProvider } from "@web3auth/base";
import { convertStringToHex, Payment, xrpToDrops } from "xrpl";
export default class XrplRPC {
private provider: IProvider;
constructor(provider: IProvider) {
this.provider = provider;
}
getAccounts = async (): Promise<any> => {
try {
const accounts = await this.provider.request<never, string[]>({
method: "xrpl_getAccounts",
});
if (accounts) {
const accInfo = await this.provider.request({
method: "account_info",
params: [
{
account: accounts[0],
strict: true,
ledger_index: "current",
queue: true,
},
],
});
return accInfo;
} else {
return "No accounts found, please report this issue.";
}
} catch (error) {
console.error("Error", error);
return error;
}
};
getBalance = async (): Promise<any> => {
try {
const accounts = await this.provider.request<string[], never>({
method: "xrpl_getAccounts",
});
if (accounts) {
const accInfo = (await this.provider.request({
method: "account_info",
params: [
{
account: accounts[0],
strict: true,
ledger_index: "current",
queue: true,
},
],
})) as Record<string, Record<string, string>>;
return accInfo.account_data?.Balance;
} else {
return "No accounts found, please report this issue.";
}
} catch (error) {
console.error("Error", error);
return error;
}
};
signMessage = async (): Promise<any> => {
try {
const msg = "Hello world";
const hexMsg = convertStringToHex(msg);
const txSign = await this.provider.request<{ signature: string }, never>({
method: "xrpl_signMessage",
params: {
signature: hexMsg,
},
});
return txSign;
} catch (error) {
console.log("error", error);
return error;
}
};
signAndSendTransaction = async (): Promise<any> => {
try {
const accounts = await this.provider.request<never, string[]>({
method: "xrpl_getAccounts",
});
if (accounts && accounts.length > 0) {
const tx: Payment = {
TransactionType: "Payment",
Account: accounts[0] as string,
Amount: xrpToDrops(50),
Destination: "rM9uB4xzDadhBTNG17KHmn3DLdenZmJwTy",
};
const txSign = await this.provider.request({
method: "xrpl_submitTransaction",
params: {
transaction: tx,
},
});
return txSign;
} else {
return "failed to fetch accounts";
}
} catch (error) {
console.log("error", error);
return error;
}
};
}