feat: adds Kadena support (#70)
This commit is contained in:
@@ -1,2 +1,2 @@
|
||||
NEXT_PUBLIC_PROJECT_ID=...
|
||||
NEXT_PUBLIC_PROJECT_ID=
|
||||
NEXT_PUBLIC_RELAY_URL=wss://relay.walletconnect.com
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
"@cosmjs/encoding": "0.31.0",
|
||||
"@cosmjs/proto-signing": "0.31.0",
|
||||
"@json-rpc-tools/utils": "1.7.6",
|
||||
"@kadena/cryptography-utils": "^0.3.2",
|
||||
"@kadena/types": "^0.3.2",
|
||||
"@multiversx/sdk-core": "11.6.0",
|
||||
"@multiversx/sdk-wallet": "4.2.0",
|
||||
"@near-wallet-selector/wallet-utils": "^7.0.2",
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 33 KiB |
@@ -18,9 +18,7 @@ interface Props {
|
||||
|
||||
export default function AccountCard({ name, logo, rgb, address, chainId }: Props) {
|
||||
const [copied, setCopied] = useState(false)
|
||||
const { activeChainId, account } = useSnapshot(
|
||||
SettingsStore.state,
|
||||
);
|
||||
const { activeChainId, account } = useSnapshot(SettingsStore.state)
|
||||
function onCopy() {
|
||||
navigator?.clipboard?.writeText(address)
|
||||
setCopied(true)
|
||||
@@ -28,8 +26,8 @@ export default function AccountCard({ name, logo, rgb, address, chainId }: Props
|
||||
}
|
||||
|
||||
async function onChainChanged(chainId: string, address: string) {
|
||||
SettingsStore.setActiveChainId(chainId);
|
||||
await updateSignClientChainId(chainId.toString(), address);
|
||||
SettingsStore.setActiveChainId(chainId)
|
||||
await updateSignClientChainId(chainId.toString(), address)
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -59,16 +57,16 @@ export default function AccountCard({ name, logo, rgb, address, chainId }: Props
|
||||
/>
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Button
|
||||
<Button
|
||||
size="sm"
|
||||
css={{
|
||||
minWidth: "auto",
|
||||
backgroundColor: "rgba(255, 255, 255, 0.15)",
|
||||
marginLeft: "$5",
|
||||
minWidth: 'auto',
|
||||
backgroundColor: 'rgba(255, 255, 255, 0.15)',
|
||||
marginLeft: '$5'
|
||||
}}
|
||||
data-testid={'chain-switch-button' + chainId}
|
||||
onPress={() => {
|
||||
onChainChanged(chainId, address);
|
||||
onChainChanged(chainId, address)
|
||||
}}
|
||||
>
|
||||
{activeChainId === chainId ? `✅` : `🔄`}
|
||||
|
||||
@@ -6,6 +6,7 @@ import { solanaAddresses } from '@/utils/SolanaWalletUtil'
|
||||
import { multiversxAddresses } from '@/utils/MultiversxWalletUtil'
|
||||
import { tronAddresses } from '@/utils/TronWalletUtil'
|
||||
import { tezosAddresses } from '@/utils/TezosWalletUtil'
|
||||
import { kadenaAddresses } from '@/utils/KadenaWalletUtil'
|
||||
import { useSnapshot } from 'valtio'
|
||||
|
||||
export default function AccountPicker() {
|
||||
@@ -21,6 +22,7 @@ export default function AccountPicker() {
|
||||
SettingsStore.setMultiversxAddress(multiversxAddresses[account])
|
||||
SettingsStore.setTronAddress(tronAddresses[account])
|
||||
SettingsStore.setTezosAddress(tezosAddresses[account])
|
||||
SettingsStore.setKadenaAddress(kadenaAddresses[account])
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
@@ -9,6 +9,7 @@ import SessionSignSolanaModal from '@/views/SessionSignSolanaModal'
|
||||
import SessionSignMultiversxModal from '@/views/SessionSignMultiversxModal'
|
||||
import SessionSignTronModal from '@/views/SessionSignTronModal'
|
||||
import SessionSignTezosModal from '@/views/SessionSignTezosModal'
|
||||
import SessionSignKadenaModal from '@/views/SessionSignKadenaModal'
|
||||
import SessionSignTypedDataModal from '@/views/SessionSignTypedDataModal'
|
||||
import SessionUnsuportedMethodModal from '@/views/SessionUnsuportedMethodModal'
|
||||
import { Modal as NextModal } from '@nextui-org/react'
|
||||
@@ -31,6 +32,7 @@ export default function Modal() {
|
||||
{view === 'SessionSignMultiversxModal' && <SessionSignMultiversxModal />}
|
||||
{view === 'SessionSignTronModal' && <SessionSignTronModal />}
|
||||
{view === 'SessionSignTezosModal' && <SessionSignTezosModal />}
|
||||
{view === 'SessionSignKadenaModal' && <SessionSignKadenaModal />}
|
||||
</NextModal>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { COSMOS_MAINNET_CHAINS, TCosmosChain } from '@/data/COSMOSData'
|
||||
import { EIP155_CHAINS, TEIP155Chain } from '@/data/EIP155Data'
|
||||
import { KADENA_CHAINS, TKadenaChain } from '@/data/KadenaData'
|
||||
import { NEAR_TEST_CHAINS, TNearChain } from '@/data/NEARData'
|
||||
import { SOLANA_CHAINS, TSolanaChain } from '@/data/SolanaData'
|
||||
import { MULTIVERSX_CHAINS, TMultiversxChain } from '@/data/MultiversxData'
|
||||
@@ -18,7 +19,7 @@ interface IProps {
|
||||
/**
|
||||
* Component
|
||||
*/
|
||||
export default function RequesDetailsCard({ chains, protocol }: IProps) {
|
||||
export default function RequestDetailsCard({ chains, protocol }: IProps) {
|
||||
return (
|
||||
<Fragment>
|
||||
<Row>
|
||||
@@ -34,6 +35,7 @@ export default function RequesDetailsCard({ chains, protocol }: IProps) {
|
||||
NEAR_TEST_CHAINS[chain as TNearChain]?.name ??
|
||||
MULTIVERSX_CHAINS[chain as TMultiversxChain]?.name ??
|
||||
TRON_CHAINS[chain as TTronChain]?.name ??
|
||||
KADENA_CHAINS[chain as TKadenaChain]?.name ??
|
||||
chain
|
||||
)
|
||||
.join(', ')}
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
/**
|
||||
* Types
|
||||
*/
|
||||
export type TKadenaChain = keyof typeof KADENA_MAINNET_CHAINS
|
||||
|
||||
/**
|
||||
* Chains
|
||||
*/
|
||||
export const KADENA_MAINNET_CHAINS = {
|
||||
'kadena:mainnet01': {
|
||||
chainId: 'mainnet01',
|
||||
name: 'Kadena',
|
||||
logo: '/chain-logos/kadena.png',
|
||||
rgb: '237, 9, 143'
|
||||
}
|
||||
}
|
||||
|
||||
export const KADENA_TEST_CHAINS = {
|
||||
'kadena:testnet04': {
|
||||
chainId: 'testnet04',
|
||||
name: 'Kadena Testnet',
|
||||
logo: '/chain-logos/kadena.png',
|
||||
rgb: '237, 9, 143'
|
||||
}
|
||||
}
|
||||
|
||||
export const KADENA_CHAINS = { ...KADENA_MAINNET_CHAINS, ...KADENA_TEST_CHAINS }
|
||||
|
||||
/**
|
||||
* Methods
|
||||
*/
|
||||
export const KADENA_SIGNING_METHODS = {
|
||||
KADENA_GET_ACCOUNTS: 'kadena_getAccounts_v1',
|
||||
KADENA_SIGN: 'kadena_sign_v1',
|
||||
KADENA_QUICKSIGN: 'kadena_quicksign_v1'
|
||||
}
|
||||
@@ -3,13 +3,14 @@ import { createOrRestoreCosmosWallet } from '@/utils/CosmosWalletUtil'
|
||||
import { createOrRestoreEIP155Wallet } from '@/utils/EIP155WalletUtil'
|
||||
import { createOrRestoreSolanaWallet } from '@/utils/SolanaWalletUtil'
|
||||
import { createOrRestorePolkadotWallet } from '@/utils/PolkadotWalletUtil'
|
||||
import { createOrRestoreNearWallet } from '@/utils/NearWalletUtil'
|
||||
import { createOrRestoreMultiversxWallet } from '@/utils/MultiversxWalletUtil'
|
||||
import { createOrRestoreTronWallet } from '@/utils/TronWalletUtil'
|
||||
import { createOrRestoreTezosWallet } from '@/utils/TezosWalletUtil'
|
||||
import { createSignClient, signClient } from '@/utils/WalletConnectUtil'
|
||||
import { createOrRestoreKadenaWallet } from '@/utils/KadenaWalletUtil'
|
||||
import { useCallback, useEffect, useRef, useState } from 'react'
|
||||
import { useSnapshot } from 'valtio'
|
||||
import { createOrRestoreNearWallet } from '@/utils/NearWalletUtil'
|
||||
|
||||
export default function useInitialization() {
|
||||
const [initialized, setInitialized] = useState(false)
|
||||
@@ -27,6 +28,7 @@ export default function useInitialization() {
|
||||
const { multiversxAddresses } = await createOrRestoreMultiversxWallet()
|
||||
const { tronAddresses } = await createOrRestoreTronWallet()
|
||||
const { tezosAddresses } = await createOrRestoreTezosWallet()
|
||||
const { kadenaAddresses } = await createOrRestoreKadenaWallet()
|
||||
|
||||
SettingsStore.setEIP155Address(eip155Addresses[0])
|
||||
SettingsStore.setCosmosAddress(cosmosAddresses[0])
|
||||
@@ -36,6 +38,7 @@ export default function useInitialization() {
|
||||
SettingsStore.setMultiversxAddress(multiversxAddresses[0])
|
||||
SettingsStore.setTronAddress(tronAddresses[0])
|
||||
SettingsStore.setTezosAddress(tezosAddresses[0])
|
||||
SettingsStore.setKadenaAddress(kadenaAddresses[0])
|
||||
await createSignClient(relayerRegionURL)
|
||||
setInitialized(true)
|
||||
} catch (err: unknown) {
|
||||
|
||||
@@ -11,6 +11,7 @@ import { useCallback, useEffect } from 'react'
|
||||
import { NEAR_SIGNING_METHODS } from '@/data/NEARData'
|
||||
import { approveNearRequest } from '@/utils/NearRequestHandlerUtil'
|
||||
import { TEZOS_SIGNING_METHODS } from '@/data/TezosData'
|
||||
import { KADENA_SIGNING_METHODS } from '@/data/KadenaData'
|
||||
|
||||
export default function useWalletConnectEventsManager(initialized: boolean) {
|
||||
/******************************************************************************
|
||||
@@ -80,6 +81,7 @@ export default function useWalletConnectEventsManager(initialized: boolean) {
|
||||
topic,
|
||||
response: await approveNearRequest(requestEvent)
|
||||
})
|
||||
|
||||
case TRON_SIGNING_METHODS.TRON_SIGN_MESSAGE:
|
||||
case TRON_SIGNING_METHODS.TRON_SIGN_TRANSACTION:
|
||||
return ModalStore.open('SessionSignTronModal', { requestEvent, requestSession })
|
||||
@@ -87,6 +89,10 @@ export default function useWalletConnectEventsManager(initialized: boolean) {
|
||||
case TEZOS_SIGNING_METHODS.TEZOS_SEND:
|
||||
case TEZOS_SIGNING_METHODS.TEZOS_SIGN:
|
||||
return ModalStore.open('SessionSignTezosModal', { requestEvent, requestSession })
|
||||
case KADENA_SIGNING_METHODS.KADENA_GET_ACCOUNTS:
|
||||
case KADENA_SIGNING_METHODS.KADENA_SIGN:
|
||||
case KADENA_SIGNING_METHODS.KADENA_QUICKSIGN:
|
||||
return ModalStore.open('SessionSignKadenaModal', { requestEvent, requestSession })
|
||||
default:
|
||||
return ModalStore.open('SessionUnsuportedMethodModal', { requestEvent, requestSession })
|
||||
}
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
import { restoreKeyPairFromSecretKey, genKeyPair, sign } from '@kadena/cryptography-utils'
|
||||
import { IKeyPair } from '@kadena/types'
|
||||
|
||||
interface IInitArguments {
|
||||
secretKey?: string
|
||||
}
|
||||
|
||||
export default class KadenaLib {
|
||||
keyPair: IKeyPair
|
||||
|
||||
constructor(keyPair: IKeyPair) {
|
||||
this.keyPair = keyPair
|
||||
}
|
||||
|
||||
static init({ secretKey }: IInitArguments) {
|
||||
const keyPair = secretKey ? restoreKeyPairFromSecretKey(secretKey) : genKeyPair()
|
||||
|
||||
return new KadenaLib(keyPair)
|
||||
}
|
||||
|
||||
public getAddress() {
|
||||
return this.keyPair.publicKey
|
||||
}
|
||||
|
||||
public getSecretKey() {
|
||||
return this.keyPair.secretKey!
|
||||
}
|
||||
|
||||
public signRequest(transaction: string) {
|
||||
const signResponse = sign(transaction.toString(), this.keyPair)
|
||||
|
||||
return { body: { cmd: transaction, sigs: [signResponse.sig] } }
|
||||
}
|
||||
|
||||
public quicksignRequest(transactions: any) {
|
||||
const transaction = transactions.commandSigDatas[0].cmd
|
||||
const signResponse = sign(transaction.toString(), this.keyPair)
|
||||
|
||||
return {
|
||||
responses: [
|
||||
{
|
||||
outcome: { result: 'success', hash: signResponse.hash },
|
||||
commandSigData: { sigs: [{ sig: signResponse.sig, pubKey: this.keyPair.publicKey }] }
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,12 +7,13 @@ import { SOLANA_MAINNET_CHAINS, SOLANA_TEST_CHAINS } from '@/data/SolanaData'
|
||||
import { POLKADOT_MAINNET_CHAINS, POLKADOT_TEST_CHAINS } from '@/data/PolkadotData'
|
||||
import { MULTIVERSX_MAINNET_CHAINS, MULTIVERSX_TEST_CHAINS } from '@/data/MultiversxData'
|
||||
import { TRON_MAINNET_CHAINS, TRON_TEST_CHAINS } from '@/data/TronData'
|
||||
import { NEAR_TEST_CHAINS } from '@/data/NEARData'
|
||||
import { TEZOS_MAINNET_CHAINS, TEZOS_TEST_CHAINS } from '@/data/TezosData'
|
||||
import { KADENA_MAINNET_CHAINS, KADENA_TEST_CHAINS } from '@/data/KadenaData'
|
||||
import SettingsStore from '@/store/SettingsStore'
|
||||
import { Text } from '@nextui-org/react'
|
||||
import { Fragment } from 'react'
|
||||
import { useSnapshot } from 'valtio'
|
||||
import { NEAR_TEST_CHAINS } from '@/data/NEARData'
|
||||
import { TEZOS_MAINNET_CHAINS, TEZOS_TEST_CHAINS } from '@/data/TezosData'
|
||||
|
||||
export default function HomePage() {
|
||||
const {
|
||||
@@ -24,37 +25,105 @@ export default function HomePage() {
|
||||
nearAddress,
|
||||
multiversxAddress,
|
||||
tronAddress,
|
||||
tezosAddress
|
||||
tezosAddress,
|
||||
kadenaAddress
|
||||
} = useSnapshot(SettingsStore.state)
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<PageHeader title="Accounts">
|
||||
<AccountPicker data-testid='account-picker' />
|
||||
<AccountPicker data-testid="account-picker" />
|
||||
</PageHeader>
|
||||
<Text h4 css={{ marginBottom: '$5' }}>
|
||||
Mainnets
|
||||
</Text>
|
||||
{Object.entries(EIP155_MAINNET_CHAINS).map(([caip10, {name, logo, rgb}]) => (
|
||||
<AccountCard key={name} name={name} logo={logo} rgb={rgb} address={eip155Address} chainId={caip10.toString()} data-testid={'chain-card-' + caip10.toString()} />
|
||||
{Object.entries(EIP155_MAINNET_CHAINS).map(([caip10, { name, logo, rgb }]) => (
|
||||
<AccountCard
|
||||
key={name}
|
||||
name={name}
|
||||
logo={logo}
|
||||
rgb={rgb}
|
||||
address={eip155Address}
|
||||
chainId={caip10.toString()}
|
||||
data-testid={'chain-card-' + caip10.toString()}
|
||||
/>
|
||||
))}
|
||||
{Object.entries(COSMOS_MAINNET_CHAINS).map(([caip10, {name, logo, rgb}]) => (
|
||||
<AccountCard key={name} name={name} logo={logo} rgb={rgb} address={cosmosAddress} chainId={caip10} data-testid={'chain-card-' + caip10}/>
|
||||
{Object.entries(COSMOS_MAINNET_CHAINS).map(([caip10, { name, logo, rgb }]) => (
|
||||
<AccountCard
|
||||
key={name}
|
||||
name={name}
|
||||
logo={logo}
|
||||
rgb={rgb}
|
||||
address={cosmosAddress}
|
||||
chainId={caip10}
|
||||
data-testid={'chain-card-' + caip10.toString()}
|
||||
/>
|
||||
))}
|
||||
{Object.entries(SOLANA_MAINNET_CHAINS).map(([caip10, {name, logo, rgb}]) => (
|
||||
<AccountCard key={name} name={name} logo={logo} rgb={rgb} address={solanaAddress} chainId={caip10} data-testid={'chain-card-' + caip10}/>
|
||||
{Object.entries(SOLANA_MAINNET_CHAINS).map(([caip10, { name, logo, rgb }]) => (
|
||||
<AccountCard
|
||||
key={name}
|
||||
name={name}
|
||||
logo={logo}
|
||||
rgb={rgb}
|
||||
address={solanaAddress}
|
||||
chainId={caip10}
|
||||
data-testid={'chain-card-' + caip10.toString()}
|
||||
/>
|
||||
))}
|
||||
{Object.entries(POLKADOT_MAINNET_CHAINS).map(([caip10, {name, logo, rgb}]) => (
|
||||
<AccountCard key={name} name={name} logo={logo} rgb={rgb} address={polkadotAddress} chainId={caip10} data-testid={'chain-card-' + caip10}/>
|
||||
{Object.entries(POLKADOT_MAINNET_CHAINS).map(([caip10, { name, logo, rgb }]) => (
|
||||
<AccountCard
|
||||
key={name}
|
||||
name={name}
|
||||
logo={logo}
|
||||
rgb={rgb}
|
||||
address={polkadotAddress}
|
||||
chainId={caip10}
|
||||
data-testid={'chain-card-' + caip10.toString()}
|
||||
/>
|
||||
))}
|
||||
{Object.entries(MULTIVERSX_MAINNET_CHAINS).map(([caip10, {name, logo, rgb}]) => (
|
||||
<AccountCard key={name} name={name} logo={logo} rgb={rgb} address={multiversxAddress} chainId={caip10} data-testid={'chain-card-' + caip10}/>
|
||||
{Object.entries(MULTIVERSX_MAINNET_CHAINS).map(([caip10, { name, logo, rgb }]) => (
|
||||
<AccountCard
|
||||
key={name}
|
||||
name={name}
|
||||
logo={logo}
|
||||
rgb={rgb}
|
||||
address={multiversxAddress}
|
||||
chainId={caip10}
|
||||
data-testid={'chain-card-' + caip10.toString()}
|
||||
/>
|
||||
))}
|
||||
{Object.entries(TRON_MAINNET_CHAINS).map(([caip10, {name, logo, rgb}]) => (
|
||||
<AccountCard key={name} name={name} logo={logo} rgb={rgb} address={tronAddress} chainId={caip10} data-testid={'chain-card-' + caip10}/>
|
||||
{Object.entries(TRON_MAINNET_CHAINS).map(([caip10, { name, logo, rgb }]) => (
|
||||
<AccountCard
|
||||
key={name}
|
||||
name={name}
|
||||
logo={logo}
|
||||
rgb={rgb}
|
||||
address={tronAddress}
|
||||
chainId={caip10}
|
||||
data-testid={'chain-card-' + caip10.toString()}
|
||||
/>
|
||||
))}
|
||||
{Object.entries(TEZOS_MAINNET_CHAINS).map(([caip10, {name, logo, rgb}]) => (
|
||||
<AccountCard key={name} name={name} logo={logo} rgb={rgb} address={tezosAddress} chainId={caip10} data-testid={'chain-card-' + caip10}/>
|
||||
{Object.entries(TEZOS_MAINNET_CHAINS).map(([caip10, { name, logo, rgb }]) => (
|
||||
<AccountCard
|
||||
key={name}
|
||||
name={name}
|
||||
logo={logo}
|
||||
rgb={rgb}
|
||||
address={tezosAddress}
|
||||
chainId={caip10}
|
||||
data-testid={'chain-card-' + caip10.toString()}
|
||||
/>
|
||||
))}
|
||||
{Object.entries(KADENA_MAINNET_CHAINS).map(([caip10, { name, logo, rgb }]) => (
|
||||
<AccountCard
|
||||
key={name}
|
||||
name={name}
|
||||
logo={logo}
|
||||
rgb={rgb}
|
||||
address={kadenaAddress}
|
||||
chainId={caip10}
|
||||
data-testid={'chain-card-' + caip10.toString()}
|
||||
/>
|
||||
))}
|
||||
|
||||
{testNets ? (
|
||||
@@ -62,26 +131,93 @@ export default function HomePage() {
|
||||
<Text h4 css={{ marginBottom: '$5' }}>
|
||||
Testnets
|
||||
</Text>
|
||||
{Object.entries(EIP155_TEST_CHAINS).map(([caip10, {name, logo, rgb}]) => (
|
||||
<AccountCard key={name} name={name} logo={logo} rgb={rgb} address={eip155Address} chainId={caip10.toString()} data-testid={'chain-card-' + caip10.toString()}/>
|
||||
{Object.entries(EIP155_TEST_CHAINS).map(([caip10, { name, logo, rgb }]) => (
|
||||
<AccountCard
|
||||
key={name}
|
||||
name={name}
|
||||
logo={logo}
|
||||
rgb={rgb}
|
||||
address={eip155Address}
|
||||
chainId={caip10.toString()}
|
||||
data-testid={'chain-card-' + caip10.toString()}
|
||||
/>
|
||||
))}
|
||||
{Object.entries(SOLANA_TEST_CHAINS).map(([caip10, {name, logo, rgb}]) => (
|
||||
<AccountCard key={name} name={name} logo={logo} rgb={rgb} address={solanaAddress} chainId={caip10} data-testid={'chain-card-' + caip10}/>
|
||||
{Object.entries(SOLANA_TEST_CHAINS).map(([caip10, { name, logo, rgb }]) => (
|
||||
<AccountCard
|
||||
key={name}
|
||||
name={name}
|
||||
logo={logo}
|
||||
rgb={rgb}
|
||||
address={solanaAddress}
|
||||
chainId={caip10}
|
||||
data-testid={'chain-card-' + caip10.toString()}
|
||||
/>
|
||||
))}
|
||||
{Object.entries(POLKADOT_TEST_CHAINS).map(([caip10, {name, logo, rgb}]) => (
|
||||
<AccountCard key={name} name={name} logo={logo} rgb={rgb} address={polkadotAddress} chainId={caip10} data-testid={'chain-card-' + caip10}/>
|
||||
{Object.entries(POLKADOT_TEST_CHAINS).map(([caip10, { name, logo, rgb }]) => (
|
||||
<AccountCard
|
||||
key={name}
|
||||
name={name}
|
||||
logo={logo}
|
||||
rgb={rgb}
|
||||
address={polkadotAddress}
|
||||
chainId={caip10}
|
||||
data-testid={'chain-card-' + caip10.toString()}
|
||||
/>
|
||||
))}
|
||||
{Object.entries(NEAR_TEST_CHAINS).map(([caip10, {name, logo, rgb}]) => (
|
||||
<AccountCard key={name} name={name} logo={logo} rgb={rgb} address={nearAddress} chainId={caip10} data-testid={'chain-card-' + caip10}/>
|
||||
{Object.entries(NEAR_TEST_CHAINS).map(([caip10, { name, logo, rgb }]) => (
|
||||
<AccountCard
|
||||
key={name}
|
||||
name={name}
|
||||
logo={logo}
|
||||
rgb={rgb}
|
||||
address={nearAddress}
|
||||
chainId={caip10}
|
||||
data-testid={'chain-card-' + caip10.toString()}
|
||||
/>
|
||||
))}
|
||||
{Object.entries(MULTIVERSX_TEST_CHAINS).map(([caip10, {name, logo, rgb}]) => (
|
||||
<AccountCard key={name} name={name} logo={logo} rgb={rgb} address={multiversxAddress} chainId={caip10} data-testid={'chain-card-' + caip10}/>
|
||||
))}
|
||||
{Object.entries(TRON_TEST_CHAINS).map(([caip10, {name, logo, rgb}]) => (
|
||||
<AccountCard key={name} name={name} logo={logo} rgb={rgb} address={tronAddress} chainId={caip10} data-testid={'chain-card-' + caip10}/>
|
||||
{Object.entries(MULTIVERSX_TEST_CHAINS).map(([caip10, { name, logo, rgb }]) => (
|
||||
<AccountCard
|
||||
key={name}
|
||||
name={name}
|
||||
logo={logo}
|
||||
rgb={rgb}
|
||||
address={multiversxAddress}
|
||||
chainId={caip10}
|
||||
data-testid={'chain-card-' + caip10.toString()}
|
||||
/>
|
||||
))}
|
||||
{Object.entries(TEZOS_TEST_CHAINS).map(([caip10, {name, logo, rgb}]) => (
|
||||
<AccountCard key={name} name={name} logo={logo} rgb={rgb} address={tezosAddress} chainId={caip10} data-testid={'chain-card-' + caip10}/>
|
||||
{Object.entries(TRON_TEST_CHAINS).map(([caip10, { name, logo, rgb }]) => (
|
||||
<AccountCard
|
||||
key={name}
|
||||
name={name}
|
||||
logo={logo}
|
||||
rgb={rgb}
|
||||
address={tronAddress}
|
||||
chainId={caip10}
|
||||
data-testid={'chain-card-' + caip10.toString()}
|
||||
/>
|
||||
))}
|
||||
{Object.entries(TEZOS_TEST_CHAINS).map(([caip10, { name, logo, rgb }]) => (
|
||||
<AccountCard
|
||||
key={name}
|
||||
name={name}
|
||||
logo={logo}
|
||||
rgb={rgb}
|
||||
address={tezosAddress}
|
||||
chainId={caip10}
|
||||
data-testid={'chain-card-' + caip10.toString()}
|
||||
/>
|
||||
))}
|
||||
{Object.entries(KADENA_TEST_CHAINS).map(([caip10, { name, logo, rgb }]) => (
|
||||
<AccountCard
|
||||
key={name}
|
||||
name={name}
|
||||
logo={logo}
|
||||
rgb={rgb}
|
||||
address={kadenaAddress}
|
||||
chainId={caip10}
|
||||
data-testid={'chain-card-' + caip10.toString()}
|
||||
/>
|
||||
))}
|
||||
</Fragment>
|
||||
) : null}
|
||||
|
||||
@@ -6,6 +6,7 @@ import { eip155Wallets } from '@/utils/EIP155WalletUtil'
|
||||
import { solanaWallets } from '@/utils/SolanaWalletUtil'
|
||||
import { multiversxWallets } from '@/utils/MultiversxWalletUtil'
|
||||
import { tronWallets } from '@/utils/TronWalletUtil'
|
||||
import { kadenaWallets } from '@/utils/KadenaWalletUtil'
|
||||
import { Card, Divider, Row, Switch, Text } from '@nextui-org/react'
|
||||
import { Fragment } from 'react'
|
||||
import { useSnapshot } from 'valtio'
|
||||
@@ -20,7 +21,8 @@ export default function SettingsPage() {
|
||||
solanaAddress,
|
||||
multiversxAddress,
|
||||
tronAddress,
|
||||
tezosAddress
|
||||
tezosAddress,
|
||||
kadenaAddress
|
||||
} = useSnapshot(SettingsStore.state)
|
||||
|
||||
return (
|
||||
@@ -94,7 +96,9 @@ export default function SettingsPage() {
|
||||
MultiversX Mnemonic
|
||||
</Text>
|
||||
<Card bordered borderWeight="light" css={{ minHeight: '215px', wordWrap: 'break-word' }}>
|
||||
<Text css={{ fontFamily: '$mono' }}>{multiversxWallets[multiversxAddress].getMnemonic()}</Text>
|
||||
<Text css={{ fontFamily: '$mono' }}>
|
||||
{multiversxWallets[multiversxAddress].getMnemonic()}
|
||||
</Text>
|
||||
</Card>
|
||||
|
||||
<Text h4 css={{ marginTop: '$10', marginBottom: '$5' }}>
|
||||
@@ -110,6 +114,15 @@ export default function SettingsPage() {
|
||||
<Card bordered borderWeight="light" css={{ minHeight: '100px', wordWrap: 'break-word' }}>
|
||||
<Text css={{ fontFamily: '$mono' }}>{tezosWallets[tezosAddress].getMnemonic()}</Text>
|
||||
</Card>
|
||||
|
||||
<Text h4 css={{ marginTop: '$10', marginBottom: '$5' }}>
|
||||
Kadena Secret Key
|
||||
</Text>
|
||||
<Card bordered borderWeight="light" css={{ wordWrap: 'break-word' }}>
|
||||
<Text css={{ fontFamily: '$mono' }}>{kadenaWallets[kadenaAddress].getSecretKey()}</Text>
|
||||
</Card>
|
||||
|
||||
<Text h4 css={{ marginTop: '$10', marginBottom: '$5' }}></Text>
|
||||
</Fragment>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ interface State {
|
||||
| 'SessionSignMultiversxModal'
|
||||
| 'SessionSignTronModal'
|
||||
| 'SessionSignTezosModal'
|
||||
| 'SessionSignKadenaModal'
|
||||
data?: ModalData
|
||||
}
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ interface State {
|
||||
multiversxAddress: string
|
||||
tronAddress: string
|
||||
tezosAddress: string
|
||||
kadenaAddress: string
|
||||
relayerRegionURL: string
|
||||
activeChainId: string
|
||||
}
|
||||
@@ -33,6 +34,7 @@ const state = proxy<State>({
|
||||
multiversxAddress: '',
|
||||
tronAddress: '',
|
||||
tezosAddress: '',
|
||||
kadenaAddress: '',
|
||||
relayerRegionURL: ''
|
||||
})
|
||||
|
||||
@@ -64,6 +66,9 @@ const SettingsStore = {
|
||||
setNearAddress(nearAddress: string) {
|
||||
state.nearAddress = nearAddress
|
||||
},
|
||||
setKadenaAddress(kadenaAddress: string) {
|
||||
state.kadenaAddress = kadenaAddress
|
||||
},
|
||||
setRelayerRegionURL(relayerRegionURL: string) {
|
||||
state.relayerRegionURL = relayerRegionURL
|
||||
},
|
||||
|
||||
@@ -6,6 +6,7 @@ import { POLKADOT_CHAINS, TPolkadotChain } from '@/data/PolkadotData'
|
||||
import { SOLANA_CHAINS, TSolanaChain } from '@/data/SolanaData'
|
||||
import { TEZOS_CHAINS, TTezosChain } from '@/data/TezosData'
|
||||
import { TRON_CHAINS, TTronChain } from '@/data/TronData'
|
||||
import { KADENA_CHAINS, TKadenaChain } from '@/data/KadenaData'
|
||||
|
||||
import { utils } from 'ethers'
|
||||
|
||||
@@ -114,6 +115,13 @@ export function isNearChain(chain: string) {
|
||||
return chain.includes('near')
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if chain is part of KADENA standard
|
||||
*/
|
||||
export function isKadenaChain(chain: string) {
|
||||
return chain.includes('kadena')
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if chain is part of MULTIVERSX standard
|
||||
*/
|
||||
@@ -146,8 +154,9 @@ export function formatChainName(chainId: string) {
|
||||
NEAR_TEST_CHAINS[chainId as TNearChain]?.name ??
|
||||
POLKADOT_CHAINS[chainId as TPolkadotChain]?.name ??
|
||||
SOLANA_CHAINS[chainId as TSolanaChain]?.name ??
|
||||
TEZOS_CHAINS[chainId as TTezosChain]?.name ??
|
||||
TRON_CHAINS[chainId as TTronChain]?.name ??
|
||||
TEZOS_CHAINS[chainId as TTezosChain]?.name ??
|
||||
KADENA_CHAINS[chainId as TKadenaChain]?.name ??
|
||||
chainId
|
||||
)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
import { KADENA_SIGNING_METHODS } from '@/data/KadenaData'
|
||||
import { formatJsonRpcError, formatJsonRpcResult } from '@json-rpc-tools/utils'
|
||||
import { SignClientTypes } from '@walletconnect/types'
|
||||
import { getSdkError } from '@walletconnect/utils'
|
||||
import { getWalletAddressFromParams } from './HelperUtil'
|
||||
import { kadenaAddresses, kadenaWallets } from './KadenaWalletUtil'
|
||||
|
||||
export async function approveKadenaRequest(
|
||||
requestEvent: SignClientTypes.EventArguments['session_request']
|
||||
) {
|
||||
const { params, id } = requestEvent
|
||||
const { request } = params
|
||||
const account = getWalletAddressFromParams(kadenaAddresses, params)
|
||||
const wallet = kadenaWallets[account]
|
||||
|
||||
switch (request.method) {
|
||||
case KADENA_SIGNING_METHODS.KADENA_GET_ACCOUNTS:
|
||||
const mockAccount = `k:${account}`
|
||||
|
||||
return formatJsonRpcResult(id, {
|
||||
accounts: [
|
||||
{
|
||||
account: mockAccount,
|
||||
publicKey: account,
|
||||
kadenaAccounts: [
|
||||
{
|
||||
name: mockAccount,
|
||||
contract: 'coin',
|
||||
chains: ['2', '4', '7', '18']
|
||||
},
|
||||
{
|
||||
name: 'w:abcdabcdabcdabcd',
|
||||
contract: 'coin',
|
||||
chains: ['8', '17']
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
case KADENA_SIGNING_METHODS.KADENA_SIGN:
|
||||
const signedRequest = wallet.signRequest(request.params)
|
||||
return formatJsonRpcResult(id, signedRequest)
|
||||
|
||||
case KADENA_SIGNING_METHODS.KADENA_QUICKSIGN:
|
||||
const signedMessage = wallet.quicksignRequest(request.params)
|
||||
return formatJsonRpcResult(id, signedMessage)
|
||||
|
||||
default:
|
||||
throw new Error(getSdkError('UNSUPPORTED_METHODS').message)
|
||||
}
|
||||
}
|
||||
|
||||
export function rejectKadenaRequest(request: SignClientTypes.EventArguments['session_request']) {
|
||||
const { id } = request
|
||||
|
||||
return formatJsonRpcError(id, getSdkError('USER_REJECTED_METHODS').message)
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
import KadenaLib from '@/lib/KadenaLib'
|
||||
|
||||
export let wallet: KadenaLib
|
||||
export let kadenaWallets: Record<string, KadenaLib>
|
||||
export let kadenaAddresses: string[]
|
||||
|
||||
/**
|
||||
* Utilities
|
||||
*/
|
||||
|
||||
export async function createOrRestoreKadenaWallet() {
|
||||
const secretKey = localStorage.getItem('KADENA_SECRET_KEY')
|
||||
|
||||
if (secretKey) {
|
||||
wallet = KadenaLib.init({ secretKey })
|
||||
} else {
|
||||
wallet = KadenaLib.init({})
|
||||
}
|
||||
|
||||
if (wallet.getSecretKey()) {
|
||||
localStorage.setItem('KADENA_SECRET_KEY', wallet.getSecretKey())
|
||||
}
|
||||
|
||||
const address = wallet.getAddress()
|
||||
kadenaAddresses = [address]
|
||||
|
||||
kadenaWallets = {
|
||||
[address]: wallet
|
||||
}
|
||||
|
||||
return {
|
||||
kadenaWallets,
|
||||
kadenaAddresses
|
||||
}
|
||||
}
|
||||
@@ -17,7 +17,8 @@ import {
|
||||
isNearChain,
|
||||
isMultiversxChain,
|
||||
isTronChain,
|
||||
isTezosChain
|
||||
isTezosChain,
|
||||
isKadenaChain
|
||||
} from '@/utils/HelperUtil'
|
||||
import { solanaAddresses } from '@/utils/SolanaWalletUtil'
|
||||
import { signClient } from '@/utils/WalletConnectUtil'
|
||||
@@ -26,6 +27,7 @@ import { SessionTypes } from '@walletconnect/types'
|
||||
import { getSdkError, mergeArrays } from '@walletconnect/utils'
|
||||
import { Fragment, useEffect, useState } from 'react'
|
||||
import { nearAddresses } from '@/utils/NearWalletUtil'
|
||||
import { kadenaAddresses } from '@/utils/KadenaWalletUtil'
|
||||
|
||||
export default function SessionProposalModal() {
|
||||
const [selectedAccounts, setSelectedAccounts] = useState<Record<string, string[]>>({})
|
||||
@@ -201,6 +203,15 @@ export default function SessionProposalModal() {
|
||||
chain={chain}
|
||||
/>
|
||||
)
|
||||
} else if (isKadenaChain(chain)) {
|
||||
return (
|
||||
<ProposalSelectSection
|
||||
addresses={kadenaAddresses}
|
||||
selectedAddresses={selectedAccounts[chain]}
|
||||
onSelect={onSelectAccount}
|
||||
chain={chain}
|
||||
/>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
import ProjectInfoCard from '@/components/ProjectInfoCard'
|
||||
import RequestDataCard from '@/components/RequestDataCard'
|
||||
import RequestDetailsCard from '@/components/RequestDetalilsCard'
|
||||
import RequestMethodCard from '@/components/RequestMethodCard'
|
||||
import RequestModalContainer from '@/components/RequestModalContainer'
|
||||
import ModalStore from '@/store/ModalStore'
|
||||
import { convertHexToUtf8, getSignParamsMessage } from '@/utils/HelperUtil'
|
||||
import { approveKadenaRequest, rejectKadenaRequest } from '@/utils/KadenaRequestHandlerUtil'
|
||||
import { signClient } from '@/utils/WalletConnectUtil'
|
||||
import { Button, Col, Divider, Modal, Row, Text } from '@nextui-org/react'
|
||||
import { Fragment } from 'react'
|
||||
|
||||
export default function SessionSignKadenaModal() {
|
||||
// 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
|
||||
|
||||
// Get message, convert it to UTF8 string if it is valid hex
|
||||
const message = convertHexToUtf8(request.params.message)
|
||||
|
||||
// Handle approve action (logic varies based on request method)
|
||||
async function onApprove() {
|
||||
if (requestEvent) {
|
||||
const response = await approveKadenaRequest(requestEvent)
|
||||
await signClient.respond({
|
||||
topic,
|
||||
response
|
||||
})
|
||||
ModalStore.close()
|
||||
}
|
||||
}
|
||||
|
||||
// Handle reject action
|
||||
async function onReject() {
|
||||
if (requestEvent) {
|
||||
const response = rejectKadenaRequest(requestEvent)
|
||||
await signClient.respond({
|
||||
topic,
|
||||
response
|
||||
})
|
||||
ModalStore.close()
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<RequestModalContainer title="Sign Message">
|
||||
<ProjectInfoCard metadata={requestSession.peer.metadata} />
|
||||
|
||||
<Divider y={2} />
|
||||
|
||||
<RequestDetailsCard chains={[chainId ?? '']} protocol={requestSession.relay.protocol} />
|
||||
|
||||
<Divider y={2} />
|
||||
|
||||
{message && (
|
||||
<>
|
||||
<Row>
|
||||
<Col>
|
||||
<Text h5>Message</Text>
|
||||
<Text color="$gray400">{message}</Text>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
<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>
|
||||
)
|
||||
}
|
||||
+356
-325
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user