refactor(dapp): support signing from different addresses on same network
This commit is contained in:
parent
d4c670bdf3
commit
3c2684f851
@ -77,25 +77,25 @@ export default function App() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const getEthereumActions = (): AccountAction[] => {
|
const getEthereumActions = (): AccountAction[] => {
|
||||||
const onSendTransaction = async (chainId: string) => {
|
const onSendTransaction = async (chainId: string, address: string) => {
|
||||||
openRequestModal();
|
openRequestModal();
|
||||||
await ethereumRpc.testSendTransaction(chainId);
|
await ethereumRpc.testSendTransaction(chainId, address);
|
||||||
};
|
};
|
||||||
const onSignTransaction = async (chainId: string) => {
|
const onSignTransaction = async (chainId: string, address: string) => {
|
||||||
openRequestModal();
|
openRequestModal();
|
||||||
await ethereumRpc.testSignTransaction(chainId);
|
await ethereumRpc.testSignTransaction(chainId, address);
|
||||||
};
|
};
|
||||||
const onSignPersonalMessage = async (chainId: string) => {
|
const onSignPersonalMessage = async (chainId: string, address: string) => {
|
||||||
openRequestModal();
|
openRequestModal();
|
||||||
await ethereumRpc.testSignPersonalMessage(chainId);
|
await ethereumRpc.testSignPersonalMessage(chainId, address);
|
||||||
};
|
};
|
||||||
const onEthSign = async (chainId: string) => {
|
const onEthSign = async (chainId: string, address: string) => {
|
||||||
openRequestModal();
|
openRequestModal();
|
||||||
await ethereumRpc.testEthSign(chainId);
|
await ethereumRpc.testEthSign(chainId, address);
|
||||||
};
|
};
|
||||||
const onSignTypedData = async (chainId: string) => {
|
const onSignTypedData = async (chainId: string, address: string) => {
|
||||||
openRequestModal();
|
openRequestModal();
|
||||||
await ethereumRpc.testSignTypedData(chainId);
|
await ethereumRpc.testSignTypedData(chainId, address);
|
||||||
};
|
};
|
||||||
|
|
||||||
return [
|
return [
|
||||||
@ -108,13 +108,13 @@ export default function App() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const getCosmosActions = (): AccountAction[] => {
|
const getCosmosActions = (): AccountAction[] => {
|
||||||
const onSignDirect = async (chainId: string) => {
|
const onSignDirect = async (chainId: string, address: string) => {
|
||||||
openRequestModal();
|
openRequestModal();
|
||||||
await cosmosRpc.testSignDirect(chainId);
|
await cosmosRpc.testSignDirect(chainId, address);
|
||||||
};
|
};
|
||||||
const onSignAmino = async (chainId: string) => {
|
const onSignAmino = async (chainId: string, address: string) => {
|
||||||
openRequestModal();
|
openRequestModal();
|
||||||
await cosmosRpc.testSignAmino(chainId);
|
await cosmosRpc.testSignAmino(chainId, address);
|
||||||
};
|
};
|
||||||
return [
|
return [
|
||||||
{ method: "cosmos_signDirect", callback: onSignDirect },
|
{ method: "cosmos_signDirect", callback: onSignDirect },
|
||||||
|
@ -155,7 +155,7 @@ const Blockchain: FC<PropsWithChildren<BlockchainProps>> = (
|
|||||||
</Column>
|
</Column>
|
||||||
</SFullWidthContainer>
|
</SFullWidthContainer>
|
||||||
) : null}
|
) : null}
|
||||||
{!!actions && actions.length ? (
|
{address && !!actions && actions.length ? (
|
||||||
<SFullWidthContainer>
|
<SFullWidthContainer>
|
||||||
<h6>Methods</h6>
|
<h6>Methods</h6>
|
||||||
{actions.map(action => (
|
{actions.map(action => (
|
||||||
@ -163,7 +163,7 @@ const Blockchain: FC<PropsWithChildren<BlockchainProps>> = (
|
|||||||
key={action.method}
|
key={action.method}
|
||||||
left
|
left
|
||||||
rgb={chain.meta.rgb}
|
rgb={chain.meta.rgb}
|
||||||
onClick={() => action.callback(chainId)}
|
onClick={() => action.callback(chainId, address)}
|
||||||
>
|
>
|
||||||
{action.method}
|
{action.method}
|
||||||
</SAction>
|
</SAction>
|
||||||
|
@ -28,18 +28,20 @@ interface IRpcResult {
|
|||||||
valid: boolean;
|
valid: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type TRpcRequestCallback = (chainId: string, address: string) => Promise<void>;
|
||||||
|
|
||||||
interface IContext {
|
interface IContext {
|
||||||
ping: () => Promise<void>;
|
ping: () => Promise<void>;
|
||||||
ethereumRpc: {
|
ethereumRpc: {
|
||||||
testSendTransaction: (chainId: string) => Promise<void>;
|
testSendTransaction: TRpcRequestCallback;
|
||||||
testSignTransaction: (chainId: string) => Promise<void>;
|
testSignTransaction: TRpcRequestCallback;
|
||||||
testEthSign: (chainId: string) => Promise<void>;
|
testEthSign: TRpcRequestCallback;
|
||||||
testSignPersonalMessage: (chainId: string) => Promise<void>;
|
testSignPersonalMessage: TRpcRequestCallback;
|
||||||
testSignTypedData: (chainId: string) => Promise<void>;
|
testSignTypedData: TRpcRequestCallback;
|
||||||
};
|
};
|
||||||
cosmosRpc: {
|
cosmosRpc: {
|
||||||
testSignDirect: (chainId: string) => Promise<void>;
|
testSignDirect: TRpcRequestCallback;
|
||||||
testSignAmino: (chainId: string) => Promise<void>;
|
testSignAmino: TRpcRequestCallback;
|
||||||
};
|
};
|
||||||
chainData: ChainNamespaces;
|
chainData: ChainNamespaces;
|
||||||
rpcResult?: IRpcResult | null;
|
rpcResult?: IRpcResult | null;
|
||||||
@ -84,18 +86,9 @@ export function JsonRpcContextProvider({ children }: { children: ReactNode | Rea
|
|||||||
setChainData(chainData);
|
setChainData(chainData);
|
||||||
};
|
};
|
||||||
|
|
||||||
const getAddressByChainId = (chainId: string) => {
|
|
||||||
const account = accounts.find(account => account.startsWith(chainId));
|
|
||||||
if (account === undefined) throw new Error(`Account for chainId ${chainId} not found.`);
|
|
||||||
const address = account.split(":").pop();
|
|
||||||
if (address === undefined) throw new Error(`Address for account ${account} is invalid`);
|
|
||||||
|
|
||||||
return address;
|
|
||||||
};
|
|
||||||
|
|
||||||
const _createJsonRpcRequestHandler =
|
const _createJsonRpcRequestHandler =
|
||||||
(rpcRequest: (...requestArgs: [any]) => Promise<IFormattedRpcResponse>) =>
|
(rpcRequest: (chainId: string, address: string) => Promise<IFormattedRpcResponse>) =>
|
||||||
async (chainId: string) => {
|
async (chainId: string, address: string) => {
|
||||||
if (typeof client === "undefined") {
|
if (typeof client === "undefined") {
|
||||||
throw new Error("WalletConnect is not initialized");
|
throw new Error("WalletConnect is not initialized");
|
||||||
}
|
}
|
||||||
@ -105,7 +98,7 @@ export function JsonRpcContextProvider({ children }: { children: ReactNode | Rea
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
setPending(true);
|
setPending(true);
|
||||||
const result = await rpcRequest(chainId);
|
const result = await rpcRequest(chainId, address);
|
||||||
setResult(result);
|
setResult(result);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
@ -151,12 +144,10 @@ export function JsonRpcContextProvider({ children }: { children: ReactNode | Rea
|
|||||||
// -------- ETHEREUM/EIP155 RPC METHODS --------
|
// -------- ETHEREUM/EIP155 RPC METHODS --------
|
||||||
|
|
||||||
const ethereumRpc = {
|
const ethereumRpc = {
|
||||||
testSendTransaction: _createJsonRpcRequestHandler(async (chainId: string) => {
|
testSendTransaction: _createJsonRpcRequestHandler(async (chainId: string, address: string) => {
|
||||||
// get ethereum address
|
const caipAccountAddress = `${chainId}:${address}`;
|
||||||
const account = accounts.find(account => account.startsWith(chainId));
|
const account = accounts.find(account => account === caipAccountAddress);
|
||||||
if (account === undefined) throw new Error("Account is not found");
|
if (account === undefined) throw new Error(`Account for ${caipAccountAddress} not found`);
|
||||||
const address = account.split(":").pop();
|
|
||||||
if (address === undefined) throw new Error("Address is invalid");
|
|
||||||
|
|
||||||
const tx = await formatTestTransaction(account);
|
const tx = await formatTestTransaction(account);
|
||||||
|
|
||||||
@ -185,8 +176,6 @@ export function JsonRpcContextProvider({ children }: { children: ReactNode | Rea
|
|||||||
console.error(error);
|
console.error(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(result);
|
|
||||||
|
|
||||||
// format displayed result
|
// format displayed result
|
||||||
return {
|
return {
|
||||||
method: "eth_sendTransaction",
|
method: "eth_sendTransaction",
|
||||||
@ -195,12 +184,10 @@ export function JsonRpcContextProvider({ children }: { children: ReactNode | Rea
|
|||||||
result,
|
result,
|
||||||
};
|
};
|
||||||
}),
|
}),
|
||||||
testSignTransaction: _createJsonRpcRequestHandler(async (chainId: string) => {
|
testSignTransaction: _createJsonRpcRequestHandler(async (chainId: string, address: string) => {
|
||||||
// get ethereum address
|
const caipAccountAddress = `${chainId}:${address}`;
|
||||||
const account = accounts.find(account => account.startsWith(chainId));
|
const account = accounts.find(account => account === caipAccountAddress);
|
||||||
if (account === undefined) throw new Error("Account is not found");
|
if (account === undefined) throw new Error(`Account for ${caipAccountAddress} not found`);
|
||||||
const address = account.split(":").pop();
|
|
||||||
if (address === undefined) throw new Error("Address is invalid");
|
|
||||||
|
|
||||||
const tx = await formatTestTransaction(account);
|
const tx = await formatTestTransaction(account);
|
||||||
|
|
||||||
@ -220,54 +207,52 @@ export function JsonRpcContextProvider({ children }: { children: ReactNode | Rea
|
|||||||
result,
|
result,
|
||||||
};
|
};
|
||||||
}),
|
}),
|
||||||
testSignPersonalMessage: _createJsonRpcRequestHandler(async (chainId: string) => {
|
testSignPersonalMessage: _createJsonRpcRequestHandler(
|
||||||
// test message
|
async (chainId: string, address: string) => {
|
||||||
const message = `My email is john@doe.com - ${Date.now()}`;
|
// test message
|
||||||
|
const message = `My email is john@doe.com - ${Date.now()}`;
|
||||||
|
|
||||||
// encode message (hex)
|
// encode message (hex)
|
||||||
const hexMsg = encoding.utf8ToHex(message, true);
|
const hexMsg = encoding.utf8ToHex(message, true);
|
||||||
|
|
||||||
const address = getAddressByChainId(chainId);
|
// personal_sign params
|
||||||
|
const params = [hexMsg, address];
|
||||||
|
|
||||||
// personal_sign params
|
// send message
|
||||||
const params = [hexMsg, address];
|
const result: string = await client!.request({
|
||||||
|
topic: session!.topic,
|
||||||
|
chainId,
|
||||||
|
request: {
|
||||||
|
method: "personal_sign",
|
||||||
|
params,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
// send message
|
// split chainId
|
||||||
const result: string = await client!.request({
|
const [namespace, reference] = chainId.split(":");
|
||||||
topic: session!.topic,
|
|
||||||
chainId,
|
const targetChainData = chainData[namespace][reference];
|
||||||
request: {
|
|
||||||
|
if (typeof targetChainData === "undefined") {
|
||||||
|
throw new Error(`Missing chain data for chainId: ${chainId}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const rpcUrl = targetChainData.rpc[0];
|
||||||
|
|
||||||
|
// verify signature
|
||||||
|
const hash = hashPersonalMessage(message);
|
||||||
|
const valid = await verifySignature(address, result, hash, rpcUrl);
|
||||||
|
|
||||||
|
// format displayed result
|
||||||
|
return {
|
||||||
method: "personal_sign",
|
method: "personal_sign",
|
||||||
params,
|
address,
|
||||||
},
|
valid,
|
||||||
});
|
result,
|
||||||
|
};
|
||||||
// split chainId
|
},
|
||||||
const [namespace, reference] = chainId.split(":");
|
),
|
||||||
|
testEthSign: _createJsonRpcRequestHandler(async (chainId: string, address: string) => {
|
||||||
const targetChainData = chainData[namespace][reference];
|
|
||||||
|
|
||||||
if (typeof targetChainData === "undefined") {
|
|
||||||
throw new Error(`Missing chain data for chainId: ${chainId}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
const rpcUrl = targetChainData.rpc[0];
|
|
||||||
|
|
||||||
// verify signature
|
|
||||||
const hash = hashPersonalMessage(message);
|
|
||||||
const valid = await verifySignature(address, result, hash, rpcUrl);
|
|
||||||
|
|
||||||
// format displayed result
|
|
||||||
return {
|
|
||||||
method: "personal_sign",
|
|
||||||
address,
|
|
||||||
valid,
|
|
||||||
result,
|
|
||||||
};
|
|
||||||
}),
|
|
||||||
testEthSign: _createJsonRpcRequestHandler(async (chainId: string) => {
|
|
||||||
const address = getAddressByChainId(chainId);
|
|
||||||
|
|
||||||
// test message
|
// test message
|
||||||
const message = `My email is john@doe.com - ${Date.now()}`;
|
const message = `My email is john@doe.com - ${Date.now()}`;
|
||||||
// encode message (hex)
|
// encode message (hex)
|
||||||
@ -308,7 +293,7 @@ export function JsonRpcContextProvider({ children }: { children: ReactNode | Rea
|
|||||||
result,
|
result,
|
||||||
};
|
};
|
||||||
}),
|
}),
|
||||||
testSignTypedData: _createJsonRpcRequestHandler(async (chainId: string) => {
|
testSignTypedData: _createJsonRpcRequestHandler(async (chainId: string, address: string) => {
|
||||||
const typedData = {
|
const typedData = {
|
||||||
types: {
|
types: {
|
||||||
Person: [
|
Person: [
|
||||||
@ -341,7 +326,6 @@ export function JsonRpcContextProvider({ children }: { children: ReactNode | Rea
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const address = getAddressByChainId(chainId);
|
|
||||||
const message = JSON.stringify(typedData);
|
const message = JSON.stringify(typedData);
|
||||||
|
|
||||||
// eth_signTypedData params
|
// eth_signTypedData params
|
||||||
@ -372,7 +356,7 @@ export function JsonRpcContextProvider({ children }: { children: ReactNode | Rea
|
|||||||
// -------- COSMOS RPC METHODS --------
|
// -------- COSMOS RPC METHODS --------
|
||||||
|
|
||||||
const cosmosRpc = {
|
const cosmosRpc = {
|
||||||
testSignDirect: _createJsonRpcRequestHandler(async (chainId: string) => {
|
testSignDirect: _createJsonRpcRequestHandler(async (chainId: string, address: string) => {
|
||||||
// test direct sign doc inputs
|
// test direct sign doc inputs
|
||||||
const inputs = {
|
const inputs = {
|
||||||
fee: [{ amount: "2000", denom: "ucosm" }],
|
fee: [{ amount: "2000", denom: "ucosm" }],
|
||||||
@ -400,8 +384,6 @@ export function JsonRpcContextProvider({ children }: { children: ReactNode | Rea
|
|||||||
reference,
|
reference,
|
||||||
);
|
);
|
||||||
|
|
||||||
const address = getAddressByChainId(chainId);
|
|
||||||
|
|
||||||
// cosmos_signDirect params
|
// cosmos_signDirect params
|
||||||
const params = {
|
const params = {
|
||||||
signerAddress: address,
|
signerAddress: address,
|
||||||
@ -435,7 +417,7 @@ export function JsonRpcContextProvider({ children }: { children: ReactNode | Rea
|
|||||||
result: result.signature.signature,
|
result: result.signature.signature,
|
||||||
};
|
};
|
||||||
}),
|
}),
|
||||||
testSignAmino: _createJsonRpcRequestHandler(async (chainId: string) => {
|
testSignAmino: _createJsonRpcRequestHandler(async (chainId: string, address: string) => {
|
||||||
// split chainId
|
// split chainId
|
||||||
const [namespace, reference] = chainId.split(":");
|
const [namespace, reference] = chainId.split(":");
|
||||||
|
|
||||||
@ -449,8 +431,6 @@ export function JsonRpcContextProvider({ children }: { children: ReactNode | Rea
|
|||||||
sequence: "54",
|
sequence: "54",
|
||||||
};
|
};
|
||||||
|
|
||||||
const address = getAddressByChainId(chainId);
|
|
||||||
|
|
||||||
// cosmos_signAmino params
|
// cosmos_signAmino params
|
||||||
const params = { signerAddress: address, signDoc };
|
const params = { signerAddress: address, signDoc };
|
||||||
|
|
||||||
|
@ -151,7 +151,7 @@ export interface ChainNamespaces {
|
|||||||
|
|
||||||
export interface AccountAction {
|
export interface AccountAction {
|
||||||
method: string;
|
method: string;
|
||||||
callback: (chainId: string) => Promise<void>;
|
callback: (chainId: string, address: string) => Promise<void>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface AccountBalances {
|
export interface AccountBalances {
|
||||||
|
Loading…
Reference in New Issue
Block a user