Skip to content

Commit

Permalink
Merge pull request #192 from LedgerHQ/feat/LIVE-13659
Browse files Browse the repository at this point in the history
feat: support switch chains [LIVE-13659]
  • Loading branch information
Justkant authored Oct 8, 2024
2 parents f5be18b + 563e3cf commit bee9da9
Show file tree
Hide file tree
Showing 14 changed files with 800 additions and 432 deletions.
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,6 @@ All Live apps are defined with a manifest. Here is one that can be used for loca
"account.list",
"account.request",
"message.sign",
"transaction.sign",
"transaction.signAndBroadcast",
"wallet.userId",
"wallet.info"
Expand Down
1 change: 0 additions & 1 deletion localManifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@
"account.list",
"account.request",
"message.sign",
"transaction.sign",
"transaction.signAndBroadcast",
"wallet.userId",
"wallet.info"
Expand Down
2 changes: 2 additions & 0 deletions src/data/methods/EIP155Data.methods.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ export const EIP155_SIGNING_METHODS = {
ETH_SIGN_TYPED_DATA_V3: "eth_signTypedData_v3",
ETH_SIGN_TYPED_DATA_V4: "eth_signTypedData_v4",
ETH_SEND_TRANSACTION: "eth_sendTransaction",
ETH_ACCOUNTS: "eth_accounts",
ETH_REQUEST_ACCOUNTS: "eth_requestAccounts",
} as const;

export type EIP155_REQUESTS =
Expand Down
39 changes: 39 additions & 0 deletions src/data/methods/Wallet.methods.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/**
* Methods
*/
export const WALLET_METHODS = {
WALLET_ADD_ETHEREUM_CHAIN: "wallet_addEthereumChain",
WALLET_SWITCH_ETHEREUM_CHAIN: "wallet_switchEthereumChain",
WALLET_GET_PERMISSIONS: "wallet_getPermissions",
WALLET_REQUEST_PERMISSIONS: "wallet_requestPermissions",
WALLET_REGISTER_ONBOARDING: "wallet_registerOnboarding",
WALLET_WATCH_ASSET: "wallet_watchAsset",
WALLET_SCAN_QR_CODE: "wallet_scanQRCode",
} as const;

export type WALLET_REQUESTS =
| {
method: typeof WALLET_METHODS.WALLET_ADD_ETHEREUM_CHAIN;
params: [
{
chainId: string;
chainName: string;
rpcUrls: string[];
iconUrls: string[];
nativeCurrency: {
name: string;
symbol: string;
decimals: number;
};
blockExplorerUrls: string[];
},
];
}
| {
method: typeof WALLET_METHODS.WALLET_SWITCH_ETHEREUM_CHAIN;
params: [
{
chainId: string;
},
];
};
19 changes: 19 additions & 0 deletions src/data/network.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,16 @@

import { Network } from "./types";

function getNetworkById(chains: Record<string, Network>) {
return Object.entries(chains).reduce<Record<Network["chainId"], string>>(
(acc, [key, network]) => {
acc[network.chainId] = key;
return acc;
},
{},
);
}

export const EIP155_CHAINS_MAINNET: Record<string, Network> = {
ethereum: {
chainId: 1,
Expand Down Expand Up @@ -108,6 +118,9 @@ export const MULTIVERS_X_CHAINS: Record<string, Network> = {
},
};

export const MULTIVERS_X_NETWORK_BY_CHAIN_ID =
getNetworkById(MULTIVERS_X_CHAINS);

export const BIP122_MAINNET_CHAINS: Record<string, Network> = {
bitcoin: {
chainId: "000000000019d6689c085ae165831e93",
Expand Down Expand Up @@ -147,6 +160,8 @@ export const BIP122_CHAINS = {
...BIP122_TEST_CHAINS,
};

export const BIP122_NETWORK_BY_CHAIN_ID = getNetworkById(BIP122_CHAINS);

export const RIPPLE_CHAINS: Record<string, Network> = {
ripple: {
chainId: "0",
Expand All @@ -157,12 +172,16 @@ export const RIPPLE_CHAINS: Record<string, Network> = {
},
};

export const RIPPLE_NETWORK_BY_CHAIN_ID = getNetworkById(RIPPLE_CHAINS);

export const EIP155_CHAINS = {
...EIP155_CHAINS_MAINNET,
...EIP155_SEPOLIA_CHAINS,
...EIP155_HOLESKY_CHAINS,
};

export const EIP155_NETWORK_BY_CHAIN_ID = getNetworkById(EIP155_CHAINS);

export const SUPPORTED_NETWORK: Record<string, Network> = {
...EIP155_CHAINS,
...MULTIVERS_X_CHAINS,
Expand Down
57 changes: 57 additions & 0 deletions src/hooks/requestHandlers/BIP122.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import type { Web3Wallet } from "@walletconnect/web3wallet/dist/types/client";
import type { Account, WalletAPIClient } from "@ledgerhq/wallet-api-client";
import {
type BIP122_REQUESTS,
BIP122_SIGNING_METHODS,
} from "@/data/methods/BIP122.methods";
import { getAccountWithAddressAndChainId } from "@/utils/generic";
import { acceptRequest, Errors, formatMessage, rejectRequest } from "./utils";

export async function handleBIP122Request(
request: BIP122_REQUESTS,
topic: string,
id: number,
chainId: string,
accounts: Account[],
client: WalletAPIClient,
web3wallet: Web3Wallet,
) {
switch (request.method) {
case BIP122_SIGNING_METHODS.BIP122_SIGN_MESSAGE: {
const accountSign = getAccountWithAddressAndChainId(
accounts,
request.params.address,
chainId,
);
if (accountSign) {
try {
const message = request.params.message;
const signedMessage = await client.message.sign(
accountSign.id,
Buffer.from(message),
);
await acceptRequest(
web3wallet,
topic,
id,
formatMessage(signedMessage),
);
} catch (error) {
await rejectRequest(web3wallet, topic, id, Errors.userDecline);
console.error(error);
}
} else {
await rejectRequest(web3wallet, topic, id, Errors.userDecline);
}
break;
}
default:
await rejectRequest(
web3wallet,
topic,
id,
Errors.unsupportedMethods,
5101,
);
}
}
121 changes: 121 additions & 0 deletions src/hooks/requestHandlers/EIP155.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
import type { Web3Wallet } from "@walletconnect/web3wallet/dist/types/client";
import type { Account, WalletAPIClient } from "@ledgerhq/wallet-api-client";
import {
EIP155_SIGNING_METHODS,
type EIP155_REQUESTS,
} from "@/data/methods/EIP155Data.methods";
import { getAccountWithAddressAndChainId } from "@/utils/generic";
import { stripHexPrefix } from "@/utils/currencyFormatter/helpers";
import { convertEthToLiveTX } from "@/utils/converters";
import { acceptRequest, Errors, formatMessage, rejectRequest } from "./utils";

export async function handleEIP155Request(
request: EIP155_REQUESTS,
topic: string,
id: number,
chainId: string,
accounts: Account[],
client: WalletAPIClient,
web3wallet: Web3Wallet,
) {
switch (request.method) {
case EIP155_SIGNING_METHODS.ETH_SIGN:
case EIP155_SIGNING_METHODS.PERSONAL_SIGN: {
const isPersonalSign =
request.method === EIP155_SIGNING_METHODS.PERSONAL_SIGN;
const accountSign = getAccountWithAddressAndChainId(
accounts,
isPersonalSign ? request.params[1] : request.params[0],
chainId,
);
if (accountSign) {
try {
const message = stripHexPrefix(
isPersonalSign ? request.params[0] : request.params[1],
);

const signedMessage = await client.message.sign(
accountSign.id,
Buffer.from(message, "hex"),
);
await acceptRequest(
web3wallet,
topic,
id,
formatMessage(signedMessage),
);
} catch (error) {
await rejectRequest(web3wallet, topic, id, Errors.userDecline);
console.error(error);
}
} else {
await rejectRequest(web3wallet, topic, id, Errors.userDecline);
}
break;
}
case EIP155_SIGNING_METHODS.ETH_SIGN_TYPED_DATA:
case EIP155_SIGNING_METHODS.ETH_SIGN_TYPED_DATA_V3:
case EIP155_SIGNING_METHODS.ETH_SIGN_TYPED_DATA_V4: {
const accountSignTyped = getAccountWithAddressAndChainId(
accounts,
request.params[0],
chainId,
);
if (accountSignTyped) {
try {
const message = stripHexPrefix(request.params[1]);

const signedMessage = await client.message.sign(
accountSignTyped.id,
Buffer.from(message),
);
await acceptRequest(
web3wallet,
topic,
id,
formatMessage(signedMessage),
);
} catch (error) {
await rejectRequest(web3wallet, topic, id, Errors.msgDecline);
console.error(error);
}
} else {
await rejectRequest(web3wallet, topic, id, Errors.msgDecline);
}
break;
}
case EIP155_SIGNING_METHODS.ETH_SIGN_TRANSACTION:
case EIP155_SIGNING_METHODS.ETH_SEND_TRANSACTION: {
const ethTx = request.params[0];
const accountTX = getAccountWithAddressAndChainId(
accounts,
ethTx.from,
chainId,
);
if (accountTX) {
try {
const liveTx = convertEthToLiveTX(ethTx);
const hash = await client.transaction.signAndBroadcast(
accountTX.id,
liveTx,
);
await acceptRequest(web3wallet, topic, id, hash);
} catch (error) {
await rejectRequest(web3wallet, topic, id, Errors.txDeclined);
console.error(error);
}
} else {
await rejectRequest(web3wallet, topic, id, Errors.txDeclined);
}
break;
}
default:
await rejectRequest(
web3wallet,
topic,
id,
Errors.unsupportedMethods,
5101,
);
}
}
Loading

0 comments on commit bee9da9

Please sign in to comment.