feat: adds Elrond support (#67)
This commit is contained in:
parent
8d2240f8d5
commit
907d61cb50
@ -3,6 +3,14 @@ const nextConfig = {
|
||||
reactStrictMode: true,
|
||||
swcMinify: true,
|
||||
distDir: "build",
|
||||
webpack(config) {
|
||||
config.resolve.fallback = {
|
||||
...config.resolve.fallback,
|
||||
fs: false,
|
||||
};
|
||||
|
||||
return config;
|
||||
},
|
||||
};
|
||||
|
||||
module.exports = nextConfig;
|
||||
|
@ -10,6 +10,8 @@
|
||||
"prettier:write": "prettier --write '**/*.{js,ts,jsx,tsx}'"
|
||||
},
|
||||
"dependencies": {
|
||||
"@elrondnetwork/erdjs": "11.1.1",
|
||||
"@elrondnetwork/erdjs-walletcore": "2.1.0",
|
||||
"@ethereumjs/tx": "^3.5.0",
|
||||
"@polkadot/util-crypto": "^10.1.2",
|
||||
"@solana/web3.js": "^1.36.0",
|
||||
|
BIN
dapps/react-dapp-v2/public/assets/elrond_logo.png
Normal file
BIN
dapps/react-dapp-v2/public/assets/elrond_logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 8.1 KiB |
55
dapps/react-dapp-v2/src/chains/elrond.ts
Normal file
55
dapps/react-dapp-v2/src/chains/elrond.ts
Normal file
@ -0,0 +1,55 @@
|
||||
import { ChainsMap } from "caip-api";
|
||||
import { NamespaceMetadata, ChainMetadata } from "../helpers";
|
||||
|
||||
// TODO: add `elrond` namespace to `caip-api` package to avoid manual specification here.
|
||||
export const ElrondChainData: ChainsMap = {
|
||||
"1": {
|
||||
id: "elrond:1",
|
||||
name: "Elrond Mainnet",
|
||||
rpc: ["https://api.elrond.com"],
|
||||
slip44: 508,
|
||||
testnet: false,
|
||||
},
|
||||
D: {
|
||||
id: "elrond:D",
|
||||
name: "Elrond Devnet",
|
||||
rpc: ["https://devnet-api.elrond.com"],
|
||||
slip44: 508,
|
||||
testnet: true,
|
||||
},
|
||||
// Keep only one Test Chain visible
|
||||
// T: {
|
||||
// id: "elrond:T",
|
||||
// name: "Elrond Testnet",
|
||||
// rpc: ["https://testnet-api.elrond.com"],
|
||||
// slip44: 508,
|
||||
// testnet: true,
|
||||
// },
|
||||
};
|
||||
|
||||
export const ElrondMetadata: NamespaceMetadata = {
|
||||
// Elrond Mainnet
|
||||
"1": {
|
||||
logo: "/assets/elrond_logo.png",
|
||||
rgb: "0, 0, 0",
|
||||
},
|
||||
// Elrond Testnet
|
||||
T: {
|
||||
logo: "/assets/elrond_logo.png",
|
||||
rgb: "0, 0, 0",
|
||||
},
|
||||
// Elrond Devnet
|
||||
D: {
|
||||
logo: "/assets/elrond_logo.png",
|
||||
rgb: "0, 0, 0",
|
||||
},
|
||||
};
|
||||
|
||||
export function getChainMetadata(chainId: string): ChainMetadata {
|
||||
const reference = chainId.split(":")[1];
|
||||
const metadata = ElrondMetadata[reference];
|
||||
if (typeof metadata === "undefined") {
|
||||
throw new Error(`No chain metadata found for chainId: ${chainId}`);
|
||||
}
|
||||
return metadata;
|
||||
}
|
@ -5,6 +5,7 @@ import * as cosmos from "./cosmos";
|
||||
import * as polkadot from "./polkadot";
|
||||
import * as solana from "./solana";
|
||||
import * as near from "./near";
|
||||
import * as elrond from "./elrond";
|
||||
|
||||
import { ChainMetadata, ChainRequestRender } from "../helpers";
|
||||
|
||||
@ -21,6 +22,8 @@ export function getChainMetadata(chainId: string): ChainMetadata {
|
||||
return solana.getChainMetadata(chainId);
|
||||
case "near":
|
||||
return near.getChainMetadata(chainId);
|
||||
case "elrond":
|
||||
return elrond.getChainMetadata(chainId);
|
||||
default:
|
||||
throw new Error(`No metadata handler for namespace ${namespace}`);
|
||||
}
|
||||
|
@ -9,6 +9,7 @@ export const DEFAULT_MAIN_CHAINS = [
|
||||
"cosmos:cosmoshub-4",
|
||||
"solana:4sGjMW1sUnHzSxGspuhpqLDx6wiyjNtZ",
|
||||
"polkadot:91b171bb158e2d3848fa23a9f1c25182",
|
||||
"elrond:1",
|
||||
];
|
||||
|
||||
export const DEFAULT_TEST_CHAINS = [
|
||||
@ -21,6 +22,7 @@ export const DEFAULT_TEST_CHAINS = [
|
||||
"solana:8E9rvCKLFQia2Y35HXjjpWzj8weVo44K",
|
||||
"polkadot:e143f23803ac50e8f6f8e62695d1ce9e",
|
||||
"near:testnet",
|
||||
"elrond:D",
|
||||
];
|
||||
|
||||
export const DEFAULT_CHAINS = [...DEFAULT_MAIN_CHAINS, ...DEFAULT_TEST_CHAINS];
|
||||
@ -96,6 +98,18 @@ export enum DEFAULT_NEAR_METHODS {
|
||||
|
||||
export enum DEFAULT_NEAR_EVENTS {}
|
||||
|
||||
/**
|
||||
* ELROND
|
||||
*/
|
||||
export enum DEFAULT_ELROND_METHODS {
|
||||
ELROND_SIGN_TRANSACTION = "erd_signTransaction",
|
||||
ELROND_SIGN_TRANSACTIONS = "erd_signTransactions",
|
||||
ELROND_SIGN_MESSAGE = "erd_signMessage",
|
||||
ELROND_SIGN_LOGIN_TOKEN = "erd_signLoginToken",
|
||||
}
|
||||
|
||||
export enum DEFAULT_ELROND_EVENTS {}
|
||||
|
||||
export const DEFAULT_GITHUB_REPO_URL =
|
||||
"https://github.com/WalletConnect/web-examples/tree/main/dapps/react-dapp-v2";
|
||||
|
||||
|
@ -8,6 +8,7 @@ import {
|
||||
} from "react";
|
||||
import { SolanaChainData } from "../chains/solana";
|
||||
import { PolkadotChainData } from "../chains/polkadot";
|
||||
import { ElrondChainData } from "../chains/elrond";
|
||||
|
||||
import { ChainNamespaces, getAllChainNamespaces } from "../helpers";
|
||||
import { NearChainData } from "../chains/near";
|
||||
@ -47,6 +48,8 @@ export function ChainDataContextProvider({
|
||||
chains = PolkadotChainData;
|
||||
} else if (namespace === "near") {
|
||||
chains = NearChainData;
|
||||
} else if (namespace === "elrond") {
|
||||
chains = ElrondChainData;
|
||||
} else {
|
||||
chains = await apiGetChainNamespace(namespace);
|
||||
}
|
||||
|
@ -31,10 +31,23 @@ import {
|
||||
DEFAULT_SOLANA_METHODS,
|
||||
DEFAULT_POLKADOT_METHODS,
|
||||
DEFAULT_NEAR_METHODS,
|
||||
DEFAULT_ELROND_METHODS,
|
||||
} from "../constants";
|
||||
import { useChainData } from "./ChainDataContext";
|
||||
import { signatureVerify, cryptoWaitReady } from "@polkadot/util-crypto";
|
||||
|
||||
import {
|
||||
Transaction as ElrondTransaction,
|
||||
TransactionPayload,
|
||||
Address,
|
||||
SignableMessage,
|
||||
ISignature,
|
||||
} from "@elrondnetwork/erdjs";
|
||||
|
||||
import { UserVerifier } from "@elrondnetwork/erdjs-walletcore/out/userVerifier";
|
||||
import { Signature } from "@elrondnetwork/erdjs-walletcore/out/signature";
|
||||
import { IVerifiable } from "@elrondnetwork/erdjs-walletcore/out/interface";
|
||||
|
||||
/**
|
||||
* Types
|
||||
*/
|
||||
@ -72,6 +85,11 @@ interface IContext {
|
||||
testSignAndSendTransaction: TRpcRequestCallback;
|
||||
testSignAndSendTransactions: TRpcRequestCallback;
|
||||
};
|
||||
elrondRpc: {
|
||||
testSignMessage: TRpcRequestCallback;
|
||||
testSignTransaction: TRpcRequestCallback;
|
||||
testSignTransactions: TRpcRequestCallback;
|
||||
};
|
||||
rpcResult?: IFormattedRpcResponse | null;
|
||||
isRpcRequestPending: boolean;
|
||||
isTestnet: boolean;
|
||||
@ -814,6 +832,198 @@ export function JsonRpcContextProvider({
|
||||
),
|
||||
};
|
||||
|
||||
// -------- ELROND RPC METHODS --------
|
||||
|
||||
const elrondRpc = {
|
||||
testSignTransaction: _createJsonRpcRequestHandler(
|
||||
async (
|
||||
chainId: string,
|
||||
address: string
|
||||
): Promise<IFormattedRpcResponse> => {
|
||||
const reference = chainId.split(":")[1];
|
||||
|
||||
const userAddress = new Address(address);
|
||||
const verifier = UserVerifier.fromAddress(userAddress);
|
||||
const transactionPayload = new TransactionPayload("testdata");
|
||||
|
||||
const testTransaction = new ElrondTransaction({
|
||||
nonce: 1,
|
||||
value: "10000000000000000000",
|
||||
receiver: Address.fromBech32(address),
|
||||
sender: userAddress,
|
||||
gasPrice: 1000000000,
|
||||
gasLimit: 50000,
|
||||
chainID: reference,
|
||||
data: transactionPayload,
|
||||
});
|
||||
const transaction = testTransaction.toPlainObject();
|
||||
|
||||
try {
|
||||
const result = await client!.request<{ signature: Buffer }>({
|
||||
chainId,
|
||||
topic: session!.topic,
|
||||
request: {
|
||||
method: DEFAULT_ELROND_METHODS.ELROND_SIGN_TRANSACTION,
|
||||
params: {
|
||||
transaction,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
testTransaction.applySignature(
|
||||
new Signature(result.signature),
|
||||
userAddress
|
||||
);
|
||||
|
||||
const valid = verifier.verify(testTransaction as IVerifiable);
|
||||
|
||||
return {
|
||||
method: DEFAULT_ELROND_METHODS.ELROND_SIGN_TRANSACTION,
|
||||
address,
|
||||
valid,
|
||||
result: result.signature.toString(),
|
||||
};
|
||||
} catch (error: any) {
|
||||
throw new Error(error);
|
||||
}
|
||||
}
|
||||
),
|
||||
testSignTransactions: _createJsonRpcRequestHandler(
|
||||
async (
|
||||
chainId: string,
|
||||
address: string
|
||||
): Promise<IFormattedRpcResponse> => {
|
||||
const reference = chainId.split(":")[1];
|
||||
|
||||
const userAddress = new Address(address);
|
||||
const verifier = UserVerifier.fromAddress(userAddress);
|
||||
const testTransactionPayload = new TransactionPayload("testdata");
|
||||
|
||||
const testTransaction = new ElrondTransaction({
|
||||
nonce: 1,
|
||||
value: "10000000000000000000",
|
||||
receiver: Address.fromBech32(address),
|
||||
sender: userAddress,
|
||||
gasPrice: 1000000000,
|
||||
gasLimit: 50000,
|
||||
chainID: reference,
|
||||
data: testTransactionPayload,
|
||||
});
|
||||
|
||||
// no data for this Transaction
|
||||
const testTransaction2 = new ElrondTransaction({
|
||||
nonce: 2,
|
||||
value: "20000000000000000000",
|
||||
receiver: Address.fromBech32(address),
|
||||
sender: userAddress,
|
||||
gasPrice: 1000000000,
|
||||
gasLimit: 50000,
|
||||
chainID: reference,
|
||||
});
|
||||
|
||||
const testTransaction3Payload = new TransactionPayload("third");
|
||||
const testTransaction3 = new ElrondTransaction({
|
||||
nonce: 3,
|
||||
value: "300000000000000000",
|
||||
receiver: Address.fromBech32(address),
|
||||
sender: userAddress,
|
||||
gasPrice: 1000000000,
|
||||
gasLimit: 50000,
|
||||
chainID: reference,
|
||||
data: testTransaction3Payload,
|
||||
});
|
||||
|
||||
const transactions = [
|
||||
testTransaction,
|
||||
testTransaction2,
|
||||
testTransaction3,
|
||||
].map((transaction) => transaction.toPlainObject());
|
||||
|
||||
try {
|
||||
const result = await client!.request<{
|
||||
signatures: { signature: Buffer }[];
|
||||
}>({
|
||||
chainId,
|
||||
topic: session!.topic,
|
||||
request: {
|
||||
method: DEFAULT_ELROND_METHODS.ELROND_SIGN_TRANSACTIONS,
|
||||
params: {
|
||||
transactions,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const valid = [
|
||||
testTransaction,
|
||||
testTransaction2,
|
||||
testTransaction3,
|
||||
].reduce((acc, current, index) => {
|
||||
current.applySignature(
|
||||
new Signature(result.signatures[index].signature),
|
||||
userAddress
|
||||
);
|
||||
|
||||
return acc && verifier.verify(current as IVerifiable);
|
||||
}, true);
|
||||
|
||||
const resultSignatures = result.signatures.map(
|
||||
(signature: any) => signature.signature
|
||||
);
|
||||
|
||||
return {
|
||||
method: DEFAULT_ELROND_METHODS.ELROND_SIGN_TRANSACTIONS,
|
||||
address,
|
||||
valid,
|
||||
result: resultSignatures.join(", "),
|
||||
};
|
||||
} catch (error: any) {
|
||||
throw new Error(error);
|
||||
}
|
||||
}
|
||||
),
|
||||
testSignMessage: _createJsonRpcRequestHandler(
|
||||
async (
|
||||
chainId: string,
|
||||
address: string
|
||||
): Promise<IFormattedRpcResponse> => {
|
||||
const userAddress = new Address(address);
|
||||
const verifier = UserVerifier.fromAddress(userAddress);
|
||||
|
||||
const testMessage = new SignableMessage({
|
||||
address: userAddress,
|
||||
message: Buffer.from(`Sign this message - ${Date.now()}`, "ascii"),
|
||||
});
|
||||
|
||||
try {
|
||||
const result = await client!.request<{ signature: Buffer }>({
|
||||
chainId,
|
||||
topic: session!.topic,
|
||||
request: {
|
||||
method: DEFAULT_ELROND_METHODS.ELROND_SIGN_MESSAGE,
|
||||
params: {
|
||||
address,
|
||||
message: testMessage.message.toString(),
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
testMessage.applySignature(new Signature(result.signature));
|
||||
|
||||
const valid = verifier.verify(testMessage);
|
||||
|
||||
return {
|
||||
method: DEFAULT_ELROND_METHODS.ELROND_SIGN_MESSAGE,
|
||||
address,
|
||||
valid,
|
||||
result: result.signature.toString(),
|
||||
};
|
||||
} catch (error: any) {
|
||||
throw new Error(error);
|
||||
}
|
||||
}
|
||||
),
|
||||
};
|
||||
|
||||
return (
|
||||
<JsonRpcContext.Provider
|
||||
value={{
|
||||
@ -823,6 +1033,7 @@ export function JsonRpcContextProvider({
|
||||
solanaRpc,
|
||||
polkadotRpc,
|
||||
nearRpc,
|
||||
elrondRpc,
|
||||
rpcResult: result,
|
||||
isRpcRequestPending: pending,
|
||||
isTestnet,
|
||||
|
@ -105,6 +105,10 @@ export async function apiGetAccountBalance(
|
||||
address: string,
|
||||
chainId: string
|
||||
): Promise<AssetData> {
|
||||
const namespace = chainId.split(":")[0];
|
||||
if (namespace !== 'eip155') {
|
||||
return { balance: "", symbol: "", name: "" };
|
||||
}
|
||||
const ethChainId = chainId.split(":")[1];
|
||||
const rpc = rpcProvidersByChainId[Number(ethChainId)];
|
||||
if (!rpc) {
|
||||
|
@ -10,6 +10,8 @@ import {
|
||||
DEFAULT_POLKADOT_METHODS,
|
||||
DEFAULT_NEAR_METHODS,
|
||||
DEFAULT_NEAR_EVENTS,
|
||||
DEFAULT_ELROND_EVENTS,
|
||||
DEFAULT_ELROND_METHODS,
|
||||
} from "../constants";
|
||||
|
||||
export const getNamespacesFromChains = (chains: string[]) => {
|
||||
@ -36,6 +38,8 @@ export const getSupportedMethodsByNamespace = (namespace: string) => {
|
||||
return Object.values(DEFAULT_POLKADOT_METHODS);
|
||||
case "near":
|
||||
return Object.values(DEFAULT_NEAR_METHODS);
|
||||
case "elrond":
|
||||
return Object.values(DEFAULT_ELROND_METHODS);
|
||||
default:
|
||||
throw new Error(`No default methods for namespace: ${namespace}`);
|
||||
}
|
||||
@ -53,6 +57,8 @@ export const getSupportedEventsByNamespace = (namespace: string) => {
|
||||
return Object.values(DEFAULT_POLKADOT_EVENTS);
|
||||
case "near":
|
||||
return Object.values(DEFAULT_NEAR_EVENTS);
|
||||
case "elrond":
|
||||
return Object.values(DEFAULT_ELROND_EVENTS);
|
||||
default:
|
||||
throw new Error(`No default events for namespace: ${namespace}`);
|
||||
}
|
||||
|
@ -13,6 +13,7 @@ import {
|
||||
DEFAULT_MAIN_CHAINS,
|
||||
DEFAULT_SOLANA_METHODS,
|
||||
DEFAULT_POLKADOT_METHODS,
|
||||
DEFAULT_ELROND_METHODS,
|
||||
DEFAULT_TEST_CHAINS,
|
||||
DEFAULT_NEAR_METHODS,
|
||||
} from "../constants";
|
||||
@ -71,6 +72,7 @@ const Home: NextPage = () => {
|
||||
solanaRpc,
|
||||
polkadotRpc,
|
||||
nearRpc,
|
||||
elrondRpc,
|
||||
isRpcRequestPending,
|
||||
rpcResult,
|
||||
isTestnet,
|
||||
@ -240,6 +242,35 @@ const Home: NextPage = () => {
|
||||
];
|
||||
};
|
||||
|
||||
const getElrondActions = (): AccountAction[] => {
|
||||
const onSignTransaction = async (chainId: string, address: string) => {
|
||||
openRequestModal();
|
||||
await elrondRpc.testSignTransaction(chainId, address);
|
||||
};
|
||||
const onSignTransactions = async (chainId: string, address: string) => {
|
||||
openRequestModal();
|
||||
await elrondRpc.testSignTransactions(chainId, address);
|
||||
};
|
||||
const onSignMessage = async (chainId: string, address: string) => {
|
||||
openRequestModal();
|
||||
await elrondRpc.testSignMessage(chainId, address);
|
||||
};
|
||||
return [
|
||||
{
|
||||
method: DEFAULT_ELROND_METHODS.ELROND_SIGN_TRANSACTION,
|
||||
callback: onSignTransaction,
|
||||
},
|
||||
{
|
||||
method: DEFAULT_ELROND_METHODS.ELROND_SIGN_TRANSACTIONS,
|
||||
callback: onSignTransactions,
|
||||
},
|
||||
{
|
||||
method: DEFAULT_ELROND_METHODS.ELROND_SIGN_MESSAGE,
|
||||
callback: onSignMessage,
|
||||
},
|
||||
];
|
||||
};
|
||||
|
||||
const getBlockchainActions = (chainId: string) => {
|
||||
const [namespace] = chainId.split(":");
|
||||
switch (namespace) {
|
||||
@ -253,6 +284,8 @@ const Home: NextPage = () => {
|
||||
return getPolkadotActions();
|
||||
case "near":
|
||||
return getNearActions();
|
||||
case "elrond":
|
||||
return getElrondActions();
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,3 +1,11 @@
|
||||
module.exports = {
|
||||
reactStrictMode: true
|
||||
reactStrictMode: true,
|
||||
webpack(config) {
|
||||
config.resolve.fallback = {
|
||||
...config.resolve.fallback,
|
||||
fs: false
|
||||
}
|
||||
|
||||
return config
|
||||
}
|
||||
}
|
||||
|
@ -12,6 +12,8 @@
|
||||
"@cosmjs/amino": "0.28.4",
|
||||
"@cosmjs/encoding": "0.28.4",
|
||||
"@cosmjs/proto-signing": "0.28.4",
|
||||
"@elrondnetwork/erdjs": "11.1.1",
|
||||
"@elrondnetwork/erdjs-walletcore": "2.1.0",
|
||||
"@json-rpc-tools/utils": "1.7.6",
|
||||
"@near-wallet-selector/wallet-utils": "^7.0.2",
|
||||
"@nextui-org/react": "1.0.8-beta.5",
|
||||
|
BIN
wallets/react-wallet-v2/public/chain-logos/elrond-1.png
Normal file
BIN
wallets/react-wallet-v2/public/chain-logos/elrond-1.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 8.1 KiB |
@ -3,6 +3,7 @@ import { cosmosAddresses } from '@/utils/CosmosWalletUtil'
|
||||
import { eip155Addresses } from '@/utils/EIP155WalletUtil'
|
||||
import { nearAddresses } from '@/utils/NearWalletUtil'
|
||||
import { solanaAddresses } from '@/utils/SolanaWalletUtil'
|
||||
import { elrondAddresses } from '@/utils/ElrondWalletUtil'
|
||||
import { useSnapshot } from 'valtio'
|
||||
|
||||
export default function AccountPicker() {
|
||||
@ -15,6 +16,7 @@ export default function AccountPicker() {
|
||||
SettingsStore.setCosmosAddress(cosmosAddresses[account])
|
||||
SettingsStore.setSolanaAddress(solanaAddresses[account])
|
||||
SettingsStore.setNearAddress(nearAddresses[account])
|
||||
SettingsStore.setElrondAddress(elrondAddresses[account])
|
||||
}
|
||||
|
||||
return (
|
||||
|
@ -6,6 +6,7 @@ import SessionRequestModal from '@/views/SessionSignModal'
|
||||
import SessionSignNearModal from '@/views/SessionSignNearModal'
|
||||
import SessionSignPolkadotModal from '@/views/SessionSignPolkadotModal'
|
||||
import SessionSignSolanaModal from '@/views/SessionSignSolanaModal'
|
||||
import SessionSignElrondModal from '@/views/SessionSignElrondModal'
|
||||
import SessionSignTypedDataModal from '@/views/SessionSignTypedDataModal'
|
||||
import SessionUnsuportedMethodModal from '@/views/SessionUnsuportedMethodModal'
|
||||
import { Modal as NextModal } from '@nextui-org/react'
|
||||
@ -25,6 +26,7 @@ export default function Modal() {
|
||||
{view === 'SessionSignSolanaModal' && <SessionSignSolanaModal />}
|
||||
{view === 'SessionSignPolkadotModal' && <SessionSignPolkadotModal />}
|
||||
{view === 'SessionSignNearModal' && <SessionSignNearModal />}
|
||||
{view === 'SessionSignElrondModal' && <SessionSignElrondModal />}
|
||||
</NextModal>
|
||||
)
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ import { COSMOS_MAINNET_CHAINS, TCosmosChain } from '@/data/COSMOSData'
|
||||
import { EIP155_CHAINS, TEIP155Chain } from '@/data/EIP155Data'
|
||||
import { NEAR_TEST_CHAINS, TNearChain } from '@/data/NEARData'
|
||||
import { SOLANA_CHAINS, TSolanaChain } from '@/data/SolanaData'
|
||||
import { ELROND_CHAINS, TElrondChain } from '@/data/ElrondData'
|
||||
import { Col, Divider, Row, Text } from '@nextui-org/react'
|
||||
import { Fragment } from 'react'
|
||||
|
||||
@ -30,6 +31,7 @@ export default function RequesDetailsCard({ chains, protocol }: IProps) {
|
||||
COSMOS_MAINNET_CHAINS[chain as TCosmosChain]?.name ??
|
||||
SOLANA_CHAINS[chain as TSolanaChain]?.name ??
|
||||
NEAR_TEST_CHAINS[chain as TNearChain]?.name ??
|
||||
ELROND_CHAINS[chain as TElrondChain]?.name ??
|
||||
chain
|
||||
)
|
||||
.join(', ')}
|
||||
|
@ -3,6 +3,7 @@ import { COSMOS_MAINNET_CHAINS } from '@/data/COSMOSData'
|
||||
import { EIP155_MAINNET_CHAINS, EIP155_TEST_CHAINS } from '@/data/EIP155Data'
|
||||
import { NEAR_TEST_CHAINS } from '@/data/NEARData'
|
||||
import { SOLANA_MAINNET_CHAINS, SOLANA_TEST_CHAINS } from '@/data/SolanaData'
|
||||
import { ELROND_MAINNET_CHAINS, ELROND_TEST_CHAINS } from '@/data/ElrondData'
|
||||
import { formatChainName } from '@/utils/HelperUtil'
|
||||
import { Col, Row, Text } from '@nextui-org/react'
|
||||
import { SessionTypes } from '@walletconnect/types'
|
||||
@ -14,10 +15,12 @@ import { Fragment } from 'react'
|
||||
const CHAIN_METADATA = {
|
||||
...COSMOS_MAINNET_CHAINS,
|
||||
...SOLANA_MAINNET_CHAINS,
|
||||
...ELROND_MAINNET_CHAINS,
|
||||
...EIP155_MAINNET_CHAINS,
|
||||
...EIP155_TEST_CHAINS,
|
||||
...SOLANA_TEST_CHAINS,
|
||||
...NEAR_TEST_CHAINS
|
||||
...NEAR_TEST_CHAINS,
|
||||
...ELROND_TEST_CHAINS
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -3,6 +3,7 @@ import { COSMOS_MAINNET_CHAINS } from '@/data/COSMOSData'
|
||||
import { EIP155_MAINNET_CHAINS, EIP155_TEST_CHAINS } from '@/data/EIP155Data'
|
||||
import { NEAR_TEST_CHAINS } from '@/data/NEARData'
|
||||
import { SOLANA_MAINNET_CHAINS, SOLANA_TEST_CHAINS } from '@/data/SolanaData'
|
||||
import { ELROND_MAINNET_CHAINS, ELROND_TEST_CHAINS } from '@/data/ElrondData'
|
||||
import { formatChainName } from '@/utils/HelperUtil'
|
||||
import { Col, Row, Text } from '@nextui-org/react'
|
||||
import { ProposalTypes } from '@walletconnect/types'
|
||||
@ -14,10 +15,12 @@ import { Fragment } from 'react'
|
||||
const CHAIN_METADATA = {
|
||||
...COSMOS_MAINNET_CHAINS,
|
||||
...SOLANA_MAINNET_CHAINS,
|
||||
...ELROND_MAINNET_CHAINS,
|
||||
...EIP155_MAINNET_CHAINS,
|
||||
...EIP155_TEST_CHAINS,
|
||||
...SOLANA_TEST_CHAINS,
|
||||
...NEAR_TEST_CHAINS
|
||||
...NEAR_TEST_CHAINS,
|
||||
...ELROND_TEST_CHAINS
|
||||
}
|
||||
|
||||
/**
|
||||
|
47
wallets/react-wallet-v2/src/data/ElrondData.ts
Normal file
47
wallets/react-wallet-v2/src/data/ElrondData.ts
Normal file
@ -0,0 +1,47 @@
|
||||
/**
|
||||
* Types
|
||||
*/
|
||||
export type TElrondChain = keyof typeof ELROND_MAINNET_CHAINS
|
||||
|
||||
/**
|
||||
* Chains
|
||||
*/
|
||||
export const ELROND_MAINNET_CHAINS = {
|
||||
'elrond:1': {
|
||||
chainId: '1',
|
||||
name: 'Elrond',
|
||||
logo: '/chain-logos/elrond-1.png',
|
||||
rgb: '43, 45, 46',
|
||||
rpc: ''
|
||||
}
|
||||
}
|
||||
|
||||
export const ELROND_TEST_CHAINS = {
|
||||
'elrond:D': {
|
||||
chainId: 'D',
|
||||
name: 'Elrond Devnet',
|
||||
logo: '/chain-logos/elrond-1.png',
|
||||
rgb: '43, 45, 46',
|
||||
rpc: ''
|
||||
}
|
||||
// Keep only one Test Chain visible
|
||||
// 'elrond:T': {
|
||||
// chainId: 'T',
|
||||
// name: 'Elrond Testnet',
|
||||
// logo: '/chain-logos/elrond-1.png',
|
||||
// rgb: '43, 45, 46',
|
||||
// rpc: ''
|
||||
// }
|
||||
}
|
||||
|
||||
export const ELROND_CHAINS = { ...ELROND_MAINNET_CHAINS, ...ELROND_TEST_CHAINS }
|
||||
|
||||
/**
|
||||
* Methods
|
||||
*/
|
||||
export const ELROND_SIGNING_METHODS = {
|
||||
ELROND_SIGN_TRANSACTION: 'erd_signTransaction',
|
||||
ELROND_SIGN_TRANSACTIONS: 'erd_signTransactions',
|
||||
ELROND_SIGN_MESSAGE: 'erd_signMessage',
|
||||
ELROND_SIGN_LOGIN_TOKEN: 'erd_signLoginToken'
|
||||
}
|
@ -3,6 +3,7 @@ import { createOrRestoreCosmosWallet } from '@/utils/CosmosWalletUtil'
|
||||
import { createOrRestoreEIP155Wallet } from '@/utils/EIP155WalletUtil'
|
||||
import { createOrRestoreSolanaWallet } from '@/utils/SolanaWalletUtil'
|
||||
import { createOrRestorePolkadotWallet } from '@/utils/PolkadotWalletUtil'
|
||||
import { createOrRestoreElrondWallet } from '@/utils/ElrondWalletUtil'
|
||||
import { createSignClient } from '@/utils/WalletConnectUtil'
|
||||
import { useCallback, useEffect, useRef, useState } from 'react'
|
||||
import { useSnapshot } from 'valtio'
|
||||
@ -21,12 +22,14 @@ export default function useInitialization() {
|
||||
const { solanaAddresses } = await createOrRestoreSolanaWallet()
|
||||
const { polkadotAddresses } = await createOrRestorePolkadotWallet()
|
||||
const { nearAddresses } = await createOrRestoreNearWallet()
|
||||
const { elrondAddresses } = await createOrRestoreElrondWallet()
|
||||
|
||||
SettingsStore.setEIP155Address(eip155Addresses[0])
|
||||
SettingsStore.setCosmosAddress(cosmosAddresses[0])
|
||||
SettingsStore.setSolanaAddress(solanaAddresses[0])
|
||||
SettingsStore.setPolkadotAddress(polkadotAddresses[0])
|
||||
SettingsStore.setNearAddress(nearAddresses[0])
|
||||
SettingsStore.setElrondAddress(elrondAddresses[0])
|
||||
|
||||
await createSignClient(relayerRegionURL)
|
||||
prevRelayerURLValue.current = relayerRegionURL
|
||||
|
@ -2,6 +2,7 @@ import { COSMOS_SIGNING_METHODS } from '@/data/COSMOSData'
|
||||
import { EIP155_SIGNING_METHODS } from '@/data/EIP155Data'
|
||||
import { SOLANA_SIGNING_METHODS } from '@/data/SolanaData'
|
||||
import { POLKADOT_SIGNING_METHODS } from '@/data/PolkadotData'
|
||||
import { ELROND_SIGNING_METHODS } from '@/data/ElrondData'
|
||||
import ModalStore from '@/store/ModalStore'
|
||||
import { signClient } from '@/utils/WalletConnectUtil'
|
||||
import { SignClientTypes } from '@walletconnect/types'
|
||||
@ -51,9 +52,11 @@ export default function useWalletConnectEventsManager(initialized: boolean) {
|
||||
case SOLANA_SIGNING_METHODS.SOLANA_SIGN_MESSAGE:
|
||||
case SOLANA_SIGNING_METHODS.SOLANA_SIGN_TRANSACTION:
|
||||
return ModalStore.open('SessionSignSolanaModal', { requestEvent, requestSession })
|
||||
|
||||
case POLKADOT_SIGNING_METHODS.POLKADOT_SIGN_MESSAGE:
|
||||
case POLKADOT_SIGNING_METHODS.POLKADOT_SIGN_TRANSACTION:
|
||||
return ModalStore.open('SessionSignPolkadotModal', { requestEvent, requestSession })
|
||||
|
||||
case NEAR_SIGNING_METHODS.NEAR_SIGN_IN:
|
||||
case NEAR_SIGNING_METHODS.NEAR_SIGN_OUT:
|
||||
case NEAR_SIGNING_METHODS.NEAR_SIGN_TRANSACTION:
|
||||
@ -63,6 +66,12 @@ export default function useWalletConnectEventsManager(initialized: boolean) {
|
||||
case NEAR_SIGNING_METHODS.NEAR_VERIFY_OWNER:
|
||||
return ModalStore.open('SessionSignNearModal', { requestEvent, requestSession })
|
||||
|
||||
case ELROND_SIGNING_METHODS.ELROND_SIGN_MESSAGE:
|
||||
case ELROND_SIGNING_METHODS.ELROND_SIGN_TRANSACTION:
|
||||
case ELROND_SIGNING_METHODS.ELROND_SIGN_TRANSACTIONS:
|
||||
case ELROND_SIGNING_METHODS.ELROND_SIGN_LOGIN_TOKEN:
|
||||
return ModalStore.open('SessionSignElrondModal', { requestEvent, requestSession })
|
||||
|
||||
case NEAR_SIGNING_METHODS.NEAR_GET_ACCOUNTS:
|
||||
return signClient.respond({
|
||||
topic,
|
||||
|
90
wallets/react-wallet-v2/src/lib/ElrondLib.ts
Normal file
90
wallets/react-wallet-v2/src/lib/ElrondLib.ts
Normal file
@ -0,0 +1,90 @@
|
||||
import { Transaction, SignableMessage } from '@elrondnetwork/erdjs'
|
||||
import { Mnemonic, UserSecretKey, UserWallet, UserSigner } from '@elrondnetwork/erdjs-walletcore'
|
||||
|
||||
/**
|
||||
* Types
|
||||
*/
|
||||
interface IInitArgs {
|
||||
mnemonic?: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Library
|
||||
*/
|
||||
export default class ElrondLib {
|
||||
wallet: UserWallet
|
||||
mnemonic: Mnemonic
|
||||
password: string
|
||||
|
||||
constructor(mnemonic: Mnemonic) {
|
||||
this.mnemonic = mnemonic
|
||||
this.password = 'password' // test purposes only
|
||||
|
||||
const secretKey = mnemonic.deriveKey(0)
|
||||
const secretKeyHex = secretKey.hex()
|
||||
let fromHex = UserSecretKey.fromString(secretKeyHex)
|
||||
this.wallet = new UserWallet(fromHex, this.password)
|
||||
}
|
||||
|
||||
static init({ mnemonic }: IInitArgs) {
|
||||
const mnemonicObj = mnemonic ? Mnemonic.fromString(mnemonic) : Mnemonic.generate()
|
||||
|
||||
return new ElrondLib(mnemonicObj)
|
||||
}
|
||||
|
||||
getMnemonic() {
|
||||
const secretKey = this.mnemonic.getWords().join(' ')
|
||||
|
||||
return secretKey
|
||||
}
|
||||
|
||||
getAddress() {
|
||||
const secretKey = UserWallet.decryptSecretKey(this.wallet.toJSON(), this.password)
|
||||
const address = secretKey.generatePublicKey().toAddress().bech32()
|
||||
|
||||
return address
|
||||
}
|
||||
|
||||
async signMessage(message: string) {
|
||||
const secretKey = UserWallet.decryptSecretKey(this.wallet.toJSON(), this.password)
|
||||
const secretKeyHex = secretKey.hex()
|
||||
|
||||
const signMessage = new SignableMessage({
|
||||
message: Buffer.from(message)
|
||||
})
|
||||
|
||||
const signer = new UserSigner(UserSecretKey.fromString(secretKeyHex))
|
||||
await signer.sign(signMessage)
|
||||
|
||||
return { signature: signMessage.signature.hex() }
|
||||
}
|
||||
|
||||
async signTransaction(transaction: any) {
|
||||
const secretKey = UserWallet.decryptSecretKey(this.wallet.toJSON(), this.password)
|
||||
const secretKeyHex = secretKey.hex()
|
||||
|
||||
const signTransaction = Transaction.fromPlainObject(transaction)
|
||||
|
||||
const signer = new UserSigner(UserSecretKey.fromString(secretKeyHex))
|
||||
await signer.sign(signTransaction)
|
||||
|
||||
return { signature: signTransaction.getSignature().hex() }
|
||||
}
|
||||
|
||||
async signTransactions(transactions: any[]) {
|
||||
const secretKey = UserWallet.decryptSecretKey(this.wallet.toJSON(), this.password)
|
||||
const secretKeyHex = secretKey.hex()
|
||||
|
||||
const signatures = await Promise.all(
|
||||
transactions.map(async (transaction: any): Promise<any> => {
|
||||
const signTransaction = Transaction.fromPlainObject(transaction)
|
||||
const signer = new UserSigner(UserSecretKey.fromString(secretKeyHex))
|
||||
await signer.sign(signTransaction)
|
||||
|
||||
return { signature: signTransaction.getSignature().hex() }
|
||||
})
|
||||
)
|
||||
|
||||
return { signatures }
|
||||
}
|
||||
}
|
@ -5,6 +5,7 @@ import { COSMOS_MAINNET_CHAINS } from '@/data/COSMOSData'
|
||||
import { EIP155_MAINNET_CHAINS, EIP155_TEST_CHAINS } from '@/data/EIP155Data'
|
||||
import { SOLANA_MAINNET_CHAINS, SOLANA_TEST_CHAINS } from '@/data/SolanaData'
|
||||
import { POLKADOT_MAINNET_CHAINS, POLKADOT_TEST_CHAINS } from '@/data/PolkadotData'
|
||||
import { ELROND_MAINNET_CHAINS, ELROND_TEST_CHAINS } from '@/data/ElrondData'
|
||||
import SettingsStore from '@/store/SettingsStore'
|
||||
import { Text } from '@nextui-org/react'
|
||||
import { Fragment } from 'react'
|
||||
@ -12,8 +13,15 @@ import { useSnapshot } from 'valtio'
|
||||
import { NEAR_TEST_CHAINS } from '@/data/NEARData'
|
||||
|
||||
export default function HomePage() {
|
||||
const { testNets, eip155Address, cosmosAddress, solanaAddress, polkadotAddress, nearAddress } =
|
||||
useSnapshot(SettingsStore.state)
|
||||
const {
|
||||
testNets,
|
||||
eip155Address,
|
||||
cosmosAddress,
|
||||
solanaAddress,
|
||||
polkadotAddress,
|
||||
nearAddress,
|
||||
elrondAddress
|
||||
} = useSnapshot(SettingsStore.state)
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
@ -35,6 +43,9 @@ export default function HomePage() {
|
||||
{Object.values(POLKADOT_MAINNET_CHAINS).map(({ name, logo, rgb }) => (
|
||||
<AccountCard key={name} name={name} logo={logo} rgb={rgb} address={polkadotAddress} />
|
||||
))}
|
||||
{Object.values(ELROND_MAINNET_CHAINS).map(({ name, logo, rgb }) => (
|
||||
<AccountCard key={name} name={name} logo={logo} rgb={rgb} address={elrondAddress} />
|
||||
))}
|
||||
|
||||
{testNets ? (
|
||||
<Fragment>
|
||||
@ -53,6 +64,9 @@ export default function HomePage() {
|
||||
{Object.values(NEAR_TEST_CHAINS).map(({ name, logo, rgb }) => (
|
||||
<AccountCard key={name} name={name} logo={logo} rgb={rgb} address={nearAddress} />
|
||||
))}
|
||||
{Object.values(ELROND_TEST_CHAINS).map(({ name, logo, rgb }) => (
|
||||
<AccountCard key={name} name={name} logo={logo} rgb={rgb} address={elrondAddress} />
|
||||
))}
|
||||
</Fragment>
|
||||
) : null}
|
||||
</Fragment>
|
||||
|
@ -4,13 +4,16 @@ import SettingsStore from '@/store/SettingsStore'
|
||||
import { cosmosWallets } from '@/utils/CosmosWalletUtil'
|
||||
import { eip155Wallets } from '@/utils/EIP155WalletUtil'
|
||||
import { solanaWallets } from '@/utils/SolanaWalletUtil'
|
||||
import { elrondWallets } from '@/utils/ElrondWalletUtil'
|
||||
import { Card, Divider, Row, Switch, Text } from '@nextui-org/react'
|
||||
import { Fragment } from 'react'
|
||||
import { useSnapshot } from 'valtio'
|
||||
import packageJSON from '../../package.json'
|
||||
|
||||
export default function SettingsPage() {
|
||||
const { testNets, eip155Address, cosmosAddress, solanaAddress } = useSnapshot(SettingsStore.state)
|
||||
const { testNets, eip155Address, cosmosAddress, solanaAddress, elrondAddress } = useSnapshot(
|
||||
SettingsStore.state
|
||||
)
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
@ -78,6 +81,13 @@ export default function SettingsPage() {
|
||||
<Card bordered borderWeight="light" css={{ minHeight: '215px', wordWrap: 'break-word' }}>
|
||||
<Text css={{ fontFamily: '$mono' }}>{solanaWallets[solanaAddress].getSecretKey()}</Text>
|
||||
</Card>
|
||||
|
||||
<Text h4 css={{ marginTop: '$10', marginBottom: '$5' }}>
|
||||
Elrond Mnemonic
|
||||
</Text>
|
||||
<Card bordered borderWeight="light" css={{ minHeight: '215px', wordWrap: 'break-word' }}>
|
||||
<Text css={{ fontFamily: '$mono' }}>{elrondWallets[elrondAddress].getMnemonic()}</Text>
|
||||
</Card>
|
||||
</Fragment>
|
||||
)
|
||||
}
|
||||
|
@ -22,6 +22,7 @@ interface State {
|
||||
| 'SessionSignSolanaModal'
|
||||
| 'SessionSignPolkadotModal'
|
||||
| 'SessionSignNearModal'
|
||||
| 'SessionSignElrondModal'
|
||||
data?: ModalData
|
||||
}
|
||||
|
||||
|
@ -11,6 +11,7 @@ interface State {
|
||||
solanaAddress: string
|
||||
polkadotAddress: string
|
||||
nearAddress: string
|
||||
elrondAddress: string
|
||||
relayerRegionURL: string
|
||||
}
|
||||
|
||||
@ -25,6 +26,7 @@ const state = proxy<State>({
|
||||
solanaAddress: '',
|
||||
polkadotAddress: '',
|
||||
nearAddress: '',
|
||||
elrondAddress: '',
|
||||
relayerRegionURL: ''
|
||||
})
|
||||
|
||||
@ -60,6 +62,10 @@ const SettingsStore = {
|
||||
state.relayerRegionURL = relayerRegionURL
|
||||
},
|
||||
|
||||
setElrondAddress(elrondAddress: string) {
|
||||
state.elrondAddress = elrondAddress
|
||||
},
|
||||
|
||||
toggleTestNets() {
|
||||
state.testNets = !state.testNets
|
||||
if (state.testNets) {
|
||||
|
@ -0,0 +1,54 @@
|
||||
import { ELROND_SIGNING_METHODS } from '@/data/ElrondData'
|
||||
import { getWalletAddressFromParams } from '@/utils/HelperUtil'
|
||||
import { elrondAddresses, elrondWallets } from '@/utils/ElrondWalletUtil'
|
||||
import { formatJsonRpcError, formatJsonRpcResult } from '@json-rpc-tools/utils'
|
||||
import { SignClientTypes } from '@walletconnect/types'
|
||||
import { getSdkError } from '@walletconnect/utils'
|
||||
|
||||
export async function approveElrondRequest(
|
||||
requestEvent: SignClientTypes.EventArguments['session_request']
|
||||
) {
|
||||
const { params, id } = requestEvent
|
||||
const { request } = params
|
||||
const account = getWalletAddressFromParams(elrondAddresses, params)
|
||||
const wallet = elrondWallets[account]
|
||||
|
||||
switch (request.method) {
|
||||
case ELROND_SIGNING_METHODS.ELROND_SIGN_MESSAGE:
|
||||
const signedMessage = await wallet.signMessage(request.params.message)
|
||||
return formatJsonRpcResult(id, signedMessage)
|
||||
|
||||
case ELROND_SIGNING_METHODS.ELROND_SIGN_TRANSACTION:
|
||||
const signTransaction = request.params.transaction
|
||||
// Transactions must be signed with the Sender's Private Key before submitting them to the Elrond Network.
|
||||
// Signing is performed with the Ed25519 algorithm.
|
||||
const signature = await wallet.signTransaction(signTransaction)
|
||||
|
||||
return formatJsonRpcResult(id, signature)
|
||||
|
||||
case ELROND_SIGNING_METHODS.ELROND_SIGN_TRANSACTIONS:
|
||||
// Elrond Allows for a Batch of Transactions to be signed
|
||||
const signTransactions = request.params.transactions
|
||||
|
||||
const signatures = await wallet.signTransactions(signTransactions)
|
||||
return formatJsonRpcResult(id, signatures)
|
||||
|
||||
case ELROND_SIGNING_METHODS.ELROND_SIGN_LOGIN_TOKEN:
|
||||
// Sometimes a dApp (and its backend) might want to reliably assign an off-chain user identity to an Elrond address.
|
||||
// On this purpose, the signing providers allow a login token to be used within the login flow - this token is signed using the wallet of the user.
|
||||
// Afterwards, a backend application would normally verify the signature of the token
|
||||
const message = `${account}${request.params.token}{}`
|
||||
const { signature: signedLoginToken } = await wallet.signMessage(message)
|
||||
|
||||
return formatJsonRpcResult(id, { signature: signedLoginToken })
|
||||
|
||||
default:
|
||||
throw new Error(getSdkError('UNSUPPORTED_METHODS').message)
|
||||
}
|
||||
}
|
||||
|
||||
export function rejectElrondRequest(request: SignClientTypes.EventArguments['session_request']) {
|
||||
const { id } = request
|
||||
|
||||
return formatJsonRpcError(id, getSdkError('USER_REJECTED_METHODS').message)
|
||||
}
|
43
wallets/react-wallet-v2/src/utils/ElrondWalletUtil.ts
Normal file
43
wallets/react-wallet-v2/src/utils/ElrondWalletUtil.ts
Normal file
@ -0,0 +1,43 @@
|
||||
import ElrondLib from '@/lib/ElrondLib'
|
||||
|
||||
export let wallet1: ElrondLib
|
||||
export let wallet2: ElrondLib
|
||||
export let elrondWallets: Record<string, ElrondLib>
|
||||
export let elrondAddresses: string[]
|
||||
|
||||
let address1: string
|
||||
let address2: string
|
||||
|
||||
/**
|
||||
* Utilities
|
||||
*/
|
||||
export async function createOrRestoreElrondWallet() {
|
||||
const mnemonic1 = localStorage.getItem('ELROND_MNEMONIC_1')
|
||||
const mnemonic2 = localStorage.getItem('ELROND_MNEMONIC_2')
|
||||
|
||||
if (mnemonic1 && mnemonic2) {
|
||||
wallet1 = await ElrondLib.init({ mnemonic: mnemonic1 })
|
||||
wallet2 = await ElrondLib.init({ mnemonic: mnemonic2 })
|
||||
} else {
|
||||
wallet1 = await ElrondLib.init({})
|
||||
wallet2 = await ElrondLib.init({})
|
||||
|
||||
// Don't store mnemonic in local storage in a production project!
|
||||
localStorage.setItem('ELROND_MNEMONIC_1', wallet1.getMnemonic())
|
||||
localStorage.setItem('ELROND_MNEMONIC_2', wallet2.getMnemonic())
|
||||
}
|
||||
|
||||
address1 = await wallet1.getAddress()
|
||||
address2 = await wallet2.getAddress()
|
||||
|
||||
elrondWallets = {
|
||||
[address1]: wallet1,
|
||||
[address2]: wallet2
|
||||
}
|
||||
elrondAddresses = Object.keys(elrondWallets)
|
||||
|
||||
return {
|
||||
elrondWallets,
|
||||
elrondAddresses
|
||||
}
|
||||
}
|
@ -2,6 +2,7 @@ import { COSMOS_MAINNET_CHAINS, TCosmosChain } from '@/data/COSMOSData'
|
||||
import { EIP155_CHAINS, TEIP155Chain } from '@/data/EIP155Data'
|
||||
import { NEAR_TEST_CHAINS, TNearChain } from '@/data/NEARData'
|
||||
import { SOLANA_CHAINS, TSolanaChain } from '@/data/SolanaData'
|
||||
import { ELROND_CHAINS, TElrondChain } from '@/data/ElrondData'
|
||||
import { utils } from 'ethers'
|
||||
|
||||
/**
|
||||
@ -109,6 +110,13 @@ export function isNearChain(chain: string) {
|
||||
return chain.includes('near')
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if chain is part of ELROND standard
|
||||
*/
|
||||
export function isElrondChain(chain: string) {
|
||||
return chain.includes('elrond')
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats chainId to its name
|
||||
*/
|
||||
@ -118,6 +126,7 @@ export function formatChainName(chainId: string) {
|
||||
COSMOS_MAINNET_CHAINS[chainId as TCosmosChain]?.name ??
|
||||
SOLANA_CHAINS[chainId as TSolanaChain]?.name ??
|
||||
NEAR_TEST_CHAINS[chainId as TNearChain]?.name ??
|
||||
ELROND_CHAINS[chainId as TElrondChain]?.name ??
|
||||
chainId
|
||||
)
|
||||
}
|
||||
|
@ -6,12 +6,14 @@ import ModalStore from '@/store/ModalStore'
|
||||
import { cosmosAddresses } from '@/utils/CosmosWalletUtil'
|
||||
import { eip155Addresses } from '@/utils/EIP155WalletUtil'
|
||||
import { polkadotAddresses } from '@/utils/PolkadotWalletUtil'
|
||||
import { elrondAddresses } from '@/utils/ElrondWalletUtil'
|
||||
import {
|
||||
isCosmosChain,
|
||||
isEIP155Chain,
|
||||
isSolanaChain,
|
||||
isPolkadotChain,
|
||||
isNearChain
|
||||
isNearChain,
|
||||
isElrondChain
|
||||
} from '@/utils/HelperUtil'
|
||||
import { solanaAddresses } from '@/utils/SolanaWalletUtil'
|
||||
import { signClient } from '@/utils/WalletConnectUtil'
|
||||
@ -138,6 +140,15 @@ export default function SessionProposalModal() {
|
||||
chain={chain}
|
||||
/>
|
||||
)
|
||||
} else if (isElrondChain(chain)) {
|
||||
return (
|
||||
<ProposalSelectSection
|
||||
addresses={elrondAddresses}
|
||||
selectedAddresses={selectedAccounts[chain]}
|
||||
onSelect={onSelectAccount}
|
||||
chain={chain}
|
||||
/>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
78
wallets/react-wallet-v2/src/views/SessionSignElrondModal.tsx
Normal file
78
wallets/react-wallet-v2/src/views/SessionSignElrondModal.tsx
Normal file
@ -0,0 +1,78 @@
|
||||
import ProjectInfoCard from '@/components/ProjectInfoCard'
|
||||
import RequestDataCard from '@/components/RequestDataCard'
|
||||
import RequesDetailsCard from '@/components/RequestDetalilsCard'
|
||||
import RequestMethodCard from '@/components/RequestMethodCard'
|
||||
import RequestModalContainer from '@/components/RequestModalContainer'
|
||||
import ModalStore from '@/store/ModalStore'
|
||||
import { approveElrondRequest, rejectElrondRequest } from '@/utils/ElrondRequestHandlerUtil'
|
||||
import { signClient } from '@/utils/WalletConnectUtil'
|
||||
import { Button, Divider, Modal, Text } from '@nextui-org/react'
|
||||
import { Fragment } from 'react'
|
||||
|
||||
export default function SessionSignElrondModal() {
|
||||
// Get request and wallet data from store
|
||||
const requestEvent = ModalStore.state.data?.requestEvent
|
||||
const requestSession = ModalStore.state.data?.requestSession
|
||||
|
||||
// Ensure request and wallet are defined
|
||||
if (!requestEvent || !requestSession) {
|
||||
return <Text>Missing request data</Text>
|
||||
}
|
||||
|
||||
// Get required request data
|
||||
const { topic, params } = requestEvent
|
||||
const { request, chainId } = params
|
||||
|
||||
// Handle approve action (logic varies based on request method)
|
||||
async function onApprove() {
|
||||
if (requestEvent) {
|
||||
const response = await approveElrondRequest(requestEvent)
|
||||
await signClient.respond({
|
||||
topic,
|
||||
response
|
||||
})
|
||||
ModalStore.close()
|
||||
}
|
||||
}
|
||||
|
||||
// Handle reject action
|
||||
async function onReject() {
|
||||
if (requestEvent) {
|
||||
const response = rejectElrondRequest(requestEvent)
|
||||
await signClient.respond({
|
||||
topic,
|
||||
response
|
||||
})
|
||||
ModalStore.close()
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<RequestModalContainer title="Sign Message">
|
||||
<ProjectInfoCard metadata={requestSession.peer.metadata} />
|
||||
|
||||
<Divider y={2} />
|
||||
|
||||
<RequesDetailsCard chains={[chainId ?? '']} protocol={requestSession.relay.protocol} />
|
||||
|
||||
<Divider y={2} />
|
||||
|
||||
<RequestDataCard data={params} />
|
||||
|
||||
<Divider y={2} />
|
||||
|
||||
<RequestMethodCard methods={[request.method]} />
|
||||
</RequestModalContainer>
|
||||
|
||||
<Modal.Footer>
|
||||
<Button auto flat color="error" onClick={onReject}>
|
||||
Reject
|
||||
</Button>
|
||||
<Button auto flat color="success" onClick={onApprove}>
|
||||
Approve
|
||||
</Button>
|
||||
</Modal.Footer>
|
||||
</Fragment>
|
||||
)
|
||||
}
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user