refactor(with-solana): handle multiple pubKeys via mapping

This commit is contained in:
Ben Kremer 2022-03-14 17:48:46 +01:00
parent 081ae11986
commit 9b59d1a94e
4 changed files with 50 additions and 39 deletions

View File

@ -49,7 +49,7 @@ export default function App() {
disconnect,
chain,
accounts,
publicKey,
publicKeys,
balances,
chainData,
isInitializing,
@ -83,14 +83,22 @@ export default function App() {
await ping();
};
const testSignTransaction = async (): Promise<IFormattedRpcResponse> => {
if (!client || !publicKey || !session) {
const testSignTransaction = async (account: string): Promise<IFormattedRpcResponse> => {
if (!client || !publicKeys || !session) {
throw new Error("WalletConnect Client not initialized properly.");
}
const transaction = new Transaction({ feePayer: publicKey }).add(
const address = account.split(":").pop();
if (!address) {
throw new Error(`Could not derive Solana address from CAIP account: ${account}`);
}
const senderPublicKey = publicKeys[address];
const transaction = new Transaction({ feePayer: senderPublicKey }).add(
SystemProgram.transfer({
fromPubkey: publicKey,
fromPubkey: senderPublicKey,
toPubkey: Keypair.generate().publicKey,
lamports: 1,
}),
@ -132,19 +140,21 @@ export default function App() {
};
const getSolanaActions = (): AccountAction[] => {
const wrapRpcRequest = (rpcRequest: () => Promise<IFormattedRpcResponse>) => async () => {
openRequestModal();
try {
setIsRpcRequestPending(true);
const result = await rpcRequest();
setRpcResult(result);
} catch (error) {
console.error("RPC request failed:", error);
setRpcResult({ result: error as string });
} finally {
setIsRpcRequestPending(false);
}
};
const wrapRpcRequest =
(rpcRequest: (account: string) => Promise<IFormattedRpcResponse>) =>
async (account: string) => {
openRequestModal();
try {
setIsRpcRequestPending(true);
const result = await rpcRequest(account);
setRpcResult(result);
} catch (error) {
console.error("RPC request failed:", error);
setRpcResult({ result: error as string });
} finally {
setIsRpcRequestPending(false);
}
};
return [
{

View File

@ -120,7 +120,7 @@ function getBlockchainDisplayData(
const Blockchain: FC<PropsWithChildren<BlockchainProps>> = (
props: PropsWithChildren<BlockchainProps>,
) => {
const { fetching, chainId, address, onClick, balances, active, actions, isTestnet } = props;
const { fetching, address, onClick, balances, active, actions, isTestnet } = props;
// if (!Object.keys(chainData).length) return null;
@ -167,7 +167,7 @@ const Blockchain: FC<PropsWithChildren<BlockchainProps>> = (
</Column>
</SFullWidthContainer>
) : null}
{!!actions && actions.length ? (
{address && !!actions && actions.length ? (
<SFullWidthContainer>
<h6>Methods</h6>
{actions.map(action => (
@ -175,7 +175,7 @@ const Blockchain: FC<PropsWithChildren<BlockchainProps>> = (
key={action.method}
left
rgb={chain.meta.rgb}
onClick={() => action.callback(chainId)}
onClick={() => action.callback(address)}
>
{action.method}
</SAction>

View File

@ -21,11 +21,6 @@ import { AccountBalances, ChainNamespaces, getAllChainNamespaces } from "../help
* Types
*/
export enum SolanaChainId {
Mainnet = "solana:4sGjMW1sUnHzSxGspuhpqLDx6wiyjNtZ",
Devnet = "solana:8E9rvCKLFQia2Y35HXjjpWzj8weVo44K",
}
export enum SolanaRpcMethod {
SOL_SIGN_TRANSACTION = "sol_signTransaction",
}
@ -36,7 +31,7 @@ interface IContext {
isInitializing: boolean;
chain: string;
pairings: string[];
publicKey?: PublicKey;
publicKeys?: Record<string, PublicKey>;
accounts: string[];
balances: AccountBalances;
chainData: ChainNamespaces;
@ -61,7 +56,7 @@ export function ClientContextProvider({ children }: { children: ReactNode | Reac
const [balances, setBalances] = useState<AccountBalances>({});
const [accounts, setAccounts] = useState<string[]>([]);
const [publicKey, setPublicKey] = useState<PublicKey>();
const [publicKeys, setPublicKeys] = useState<Record<string, PublicKey>>();
const [chainData, setChainData] = useState<ChainNamespaces>({});
const [chain, setChain] = useState<string>("");
@ -69,7 +64,7 @@ export function ClientContextProvider({ children }: { children: ReactNode | Reac
setPairings([]);
setSession(undefined);
setBalances({});
setPublicKey(undefined);
setPublicKeys(undefined);
setAccounts([]);
setChain("");
};
@ -94,17 +89,23 @@ export function ClientContextProvider({ children }: { children: ReactNode | Reac
};
const onSessionConnected = useCallback(async (_session: SessionTypes.Settled) => {
const account = _session.state.accounts[0].split(":").pop();
if (!account) {
throw new Error("Could not derive account address from `session.state.accounts`.");
}
const _publicKey = new PublicKey(account);
// Create a map of Solana address -> publicKey.
const _publicKeys = _session.state.accounts.reduce(
(publicKeysMap: Record<string, PublicKey>, account) => {
const address = account.split(":").pop();
if (!address) {
throw new Error(`Could not derive Solana address from CAIP account: ${account}`);
}
publicKeysMap[address] = new PublicKey(address);
return publicKeysMap;
},
{},
);
setSession(_session);
setChain(_session.permissions.blockchain.chains[0]);
setAccounts(_session.state.accounts);
setPublicKey(_publicKey);
setPublicKeys(_publicKeys);
}, []);
const disconnect = useCallback(async () => {
@ -236,7 +237,7 @@ export function ClientContextProvider({ children }: { children: ReactNode | Reac
pairings,
isInitializing,
balances,
publicKey,
publicKeys,
accounts,
chain,
client,
@ -249,7 +250,7 @@ export function ClientContextProvider({ children }: { children: ReactNode | Reac
pairings,
isInitializing,
balances,
publicKey,
publicKeys,
accounts,
chain,
client,

View File

@ -150,7 +150,7 @@ export interface ChainNamespaces {
export interface AccountAction {
method: string;
callback: (chainId: string) => Promise<void>;
callback: (account: string) => Promise<void>;
}
export interface AccountBalances {