Add Tezos Support (#127)

* feat(): add tezos

* feat(dapp): add tezos support

* feat(): remove unused project

* feat(): update logo

* feat(): add tezos sign modal

* feat(): remove unimplemented method

* feat(tezos): add send and sign support

* feat(tezos): add rpc

* Update wallets/react-wallet-v2/src/views/SessionProposalModal.tsx

Co-authored-by: Ben Kremer <contact@bkrem.dev>

* feat(): share all accounts

---------

Co-authored-by: Ben Kremer <ben@walletconnect.com>
Co-authored-by: Ben Kremer <contact@bkrem.dev>
This commit is contained in:
AndreasGassmann
2023-03-31 10:35:53 +02:00
committed by GitHub
co-authored by Ben Kremer Ben Kremer
parent 757ed43909
commit 9bf2b02602
27 changed files with 857 additions and 14 deletions
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 26.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.0" id="katman_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 800 600" style="enable-background:new 0 0 800 600;" xml:space="preserve">
<style type="text/css">
.st0{fill:#2C7DF7;}
.st1{fill:#FFFFFF;}
</style>
<path class="st0" d="M399.8,559.9c143.8,0,260.3-116.6,260.3-260.3S543.6,39.2,399.8,39.2c-143.8,0-260.3,116.6-260.3,260.3
S256,559.9,399.8,559.9z"/>
<path class="st1" d="M424.8,449.1c-21.1,0-36.4-5.1-46.1-15.2c-9-8.6-14.2-20.4-14.5-32.8c-0.1-3.8,0.8-7.5,2.5-10.8
c1.7-2.9,4-5.3,6.9-6.9c3.3-1.7,7-2.5,10.8-2.5c3.7,0,7.4,0.9,10.8,2.5c2.9,1.6,5.2,4,6.9,6.9c1.8,3.3,2.7,7.1,2.6,10.8
c0.2,4.5-1.1,9-3.7,12.7c-2.2,3-5.2,5.3-8.8,6.4c3.5,4.4,8.4,7.5,13.8,8.6c6.1,1.8,12.5,2.7,18.9,2.7c8.4,0.1,16.7-2.4,23.7-7.1
c7.3-5.1,12.7-12.5,15.5-21c3.5-10.1,5.2-20.7,5.1-31.4c0.3-11.1-1.6-22.2-5.5-32.6c-3-8.3-8.6-15.5-16-20.3
c-6.9-4.4-14.9-6.6-23-6.6c-7.1,0.6-14,2.9-20,6.8l-14.8,7.4v-7.4l66.5-89.2h-92.2v92.6c-0.3,6.7,1.5,13.3,5.1,18.9
c1.7,2.5,4.1,4.4,6.8,5.7c2.7,1.3,5.7,1.9,8.7,1.7c5.5-0.1,10.9-2,15.3-5.4c5-3.6,9.3-8.1,12.8-13.2c0.3-0.9,0.9-1.7,1.7-2.2
c0.6-0.5,1.4-0.8,2.2-0.8c1.6,0.1,3.1,0.8,4.3,1.8c1.5,1.7,2.4,4,2.3,6.3c-0.2,1.6-0.5,3.1-0.8,4.6c-3.3,7.9-8.8,14.7-15.8,19.6
c-6.5,4.4-14.3,6.8-22.2,6.7c-20,0-33.8-3.9-41.5-11.8c-4-4.3-7-9.4-9-15c-2-5.5-2.8-11.4-2.5-17.3v-92.4h-46.9v-17.2H332v-39.2
l-10.8-10.8v-8.8h31.3l11.8,6.1v52.7l121.8-0.4l12.1,12.2l-74.7,75c4.5-1.8,9.3-3,14.1-3.4c9.6,0.4,18.9,3.1,27.3,7.8
c9.7,4.6,17.8,11.9,23.5,21c5.1,7.7,8.7,16.3,10.6,25.3c1.6,7.1,2.4,14.4,2.5,21.7c0,13.9-3.1,27.6-9.2,40.1
c-5.8,12.1-15.6,21.9-27.7,27.7C452.3,446,438.6,449.1,424.8,449.1L424.8,449.1z"/>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

+5
View File
@@ -7,6 +7,7 @@ import * as solana from "./solana";
import * as near from "./near";
import * as elrond from "./elrond";
import * as tron from "./tron";
import * as tezos from "./tezos";
import { ChainMetadata, ChainRequestRender } from "../helpers";
@@ -27,6 +28,8 @@ export function getChainMetadata(chainId: string): ChainMetadata {
return elrond.getChainMetadata(chainId);
case "tron":
return tron.getChainMetadata(chainId);
case "tezos":
return tezos.getChainMetadata(chainId);
default:
throw new Error(`No metadata handler for namespace ${namespace}`);
}
@@ -46,6 +49,8 @@ export function getChainRequestRender(
return polkadot.getChainRequestRender(request);
case "near":
return near.getChainRequestRender(request);
case "tezos":
return tezos.getChainRequestRender(request);
default:
throw new Error(`No render handler for namespace ${namespace}`);
}
+64
View File
@@ -0,0 +1,64 @@
import { JsonRpcRequest } from "@walletconnect/jsonrpc-utils";
import {
NamespaceMetadata,
ChainMetadata,
ChainRequestRender,
ChainsMap,
} from "../helpers";
export const TezosMetadata: NamespaceMetadata = {
mainnet: {
logo: "/assets/tezos.svg",
rgb: "44, 125, 247",
},
testnet: {
logo: "/assets/tezos.svg",
rgb: "44, 125, 247",
},
};
export const TezosChainData: ChainsMap = {
mainnet: {
name: "Tezos",
id: "tezos:mainnet",
rpc: ["https://mainnet.api.tez.ie"],
slip44: 1729,
testnet: false,
},
testnet: {
name: "Tezos Testnet",
id: "tezos:testnet",
rpc: ["https://ghostnet.ecadinfra.com"],
slip44: 1729,
testnet: true,
},
};
export function getChainMetadata(chainId: string): ChainMetadata {
const reference = chainId.split(":")[1];
const metadata = TezosMetadata[reference];
if (typeof metadata === "undefined") {
throw new Error(`No chain metadata found for chainId: ${chainId}`);
}
return metadata;
}
export function getChainRequestRender(
request: JsonRpcRequest
): ChainRequestRender[] {
let params = [{ label: "Method", value: request.method }];
switch (request.method) {
default:
params = [
...params,
{
label: "params",
value: JSON.stringify(request.params, null, "\t"),
},
];
break;
}
return params;
}
@@ -14,6 +14,7 @@ export const DEFAULT_MAIN_CHAINS = [
"polkadot:91b171bb158e2d3848fa23a9f1c25182",
"elrond:1",
"tron:0x2b6653dc",
"tezos:mainnet",
];
export const DEFAULT_TEST_CHAINS = [
@@ -28,6 +29,7 @@ export const DEFAULT_TEST_CHAINS = [
"near:testnet",
"elrond:D",
"tron:0xcd8690dc",
"tezos:testnet",
];
export const DEFAULT_CHAINS = [...DEFAULT_MAIN_CHAINS, ...DEFAULT_TEST_CHAINS];
@@ -125,6 +127,17 @@ export enum DEFAULT_TRON_METHODS {
export enum DEFAULT_TRON_EVENTS {}
/**
* TEZOS
*/
export enum DEFAULT_TEZOS_METHODS {
TEZOS_GET_ACCOUNTS = "tezos_getAccounts",
TEZOS_SEND = "tezos_send",
TEZOS_SIGN = "tezos_sign",
}
export enum DEFAULT_TEZOS_EVENTS {}
export const DEFAULT_GITHUB_REPO_URL =
"https://github.com/WalletConnect/web-examples/tree/main/dapps/react-dapp-v2";
@@ -14,6 +14,7 @@ import { ChainNamespaces, ChainsMap, getAllChainNamespaces } from "../helpers";
import { NearChainData } from "../chains/near";
import { CosmosChainData } from "../chains/cosmos";
import { EIP155ChainData } from "../chains/eip155";
import { TezosChainData } from "../chains/tezos";
/**
* Types
@@ -65,6 +66,9 @@ export function ChainDataContextProvider({
case "eip155":
chains = EIP155ChainData;
break;
case "tezos":
chains = TezosChainData;
break;
default:
console.error("Unknown chain namespace: ", namespace);
}
@@ -35,6 +35,7 @@ import {
DEFAULT_NEAR_METHODS,
DEFAULT_ELROND_METHODS,
DEFAULT_TRON_METHODS,
DEFAULT_TEZOS_METHODS,
} from "../constants";
import { useChainData } from "./ChainDataContext";
import { signatureVerify, cryptoWaitReady } from "@polkadot/util-crypto";
@@ -97,6 +98,11 @@ interface IContext {
testSignMessage: TRpcRequestCallback;
testSignTransaction: TRpcRequestCallback;
};
tezosRpc: {
testGetAccounts: TRpcRequestCallback;
testSignMessage: TRpcRequestCallback;
testSignTransaction: TRpcRequestCallback;
};
rpcResult?: IFormattedRpcResponse | null;
isRpcRequestPending: boolean;
isTestnet: boolean;
@@ -1154,6 +1160,103 @@ export function JsonRpcContextProvider({
),
};
// -------- TEZOS RPC METHODS --------
const tezosRpc = {
testGetAccounts: _createJsonRpcRequestHandler(
async (
chainId: string,
address: string
): Promise<IFormattedRpcResponse> => {
try {
const result = await client!.request<{ signature: string }>({
chainId,
topic: session!.topic,
request: {
method: DEFAULT_TEZOS_METHODS.TEZOS_GET_ACCOUNTS,
params: {},
},
});
return {
method: DEFAULT_TEZOS_METHODS.TEZOS_GET_ACCOUNTS,
address,
valid: true,
result: JSON.stringify(result, null, 2),
};
} catch (error: any) {
throw new Error(error.message);
}
}
),
testSignTransaction: _createJsonRpcRequestHandler(
async (
chainId: string,
address: string
): Promise<IFormattedRpcResponse> => {
try {
const result = await client!.request<{ hash: string }>({
chainId,
topic: session!.topic,
request: {
method: DEFAULT_TEZOS_METHODS.TEZOS_SEND,
params: {
account: address,
operations: [
{
kind: "transaction",
amount: "1", // 1 mutez, smallest unit
destination: address, // send to ourselves
},
],
},
},
});
return {
method: DEFAULT_TEZOS_METHODS.TEZOS_SEND,
address,
valid: true,
result: result.hash,
};
} catch (error: any) {
throw new Error(error.message);
}
}
),
testSignMessage: _createJsonRpcRequestHandler(
async (
chainId: string,
address: string
): Promise<IFormattedRpcResponse> => {
const payload = "05010000004254";
try {
const result = await client!.request<{ signature: string }>({
chainId,
topic: session!.topic,
request: {
method: DEFAULT_TEZOS_METHODS.TEZOS_SIGN,
params: {
account: address,
payload,
},
},
});
return {
method: DEFAULT_TEZOS_METHODS.TEZOS_SIGN,
address,
valid: true,
result: result.signature,
};
} catch (error: any) {
throw new Error(error.message);
}
}
),
};
return (
<JsonRpcContext.Provider
value={{
@@ -1165,6 +1268,7 @@ export function JsonRpcContextProvider({
nearRpc,
elrondRpc,
tronRpc,
tezosRpc,
rpcResult: result,
isRpcRequestPending: pending,
isTestnet,
@@ -14,6 +14,8 @@ import {
DEFAULT_ELROND_METHODS,
DEFAULT_TRON_METHODS,
DEFAULT_TRON_EVENTS,
DEFAULT_TEZOS_METHODS,
DEFAULT_TEZOS_EVENTS,
} from "../constants";
export const getNamespacesFromChains = (chains: string[]) => {
@@ -44,6 +46,8 @@ export const getSupportedMethodsByNamespace = (namespace: string) => {
return Object.values(DEFAULT_ELROND_METHODS);
case "tron":
return Object.values(DEFAULT_TRON_METHODS);
case "tezos":
return Object.values(DEFAULT_TEZOS_METHODS);
default:
throw new Error(`No default methods for namespace: ${namespace}`);
}
@@ -65,6 +69,8 @@ export const getSupportedEventsByNamespace = (namespace: string) => {
return Object.values(DEFAULT_ELROND_EVENTS);
case "tron":
return Object.values(DEFAULT_TRON_EVENTS);
case "tezos":
return Object.values(DEFAULT_TEZOS_EVENTS);
default:
throw new Error(`No default events for namespace: ${namespace}`);
}
+33
View File
@@ -17,6 +17,7 @@ import {
DEFAULT_TEST_CHAINS,
DEFAULT_NEAR_METHODS,
DEFAULT_TRON_METHODS,
DEFAULT_TEZOS_METHODS,
} from "../constants";
import { AccountAction, setLocaleStorageTestnetFlag } from "../helpers";
import Toggle from "../components/Toggle";
@@ -75,6 +76,7 @@ const Home: NextPage = () => {
nearRpc,
elrondRpc,
tronRpc,
tezosRpc,
isRpcRequestPending,
rpcResult,
isTestnet,
@@ -306,6 +308,35 @@ const Home: NextPage = () => {
];
};
const getTezosActions = (): AccountAction[] => {
const onGetAccounts = async (chainId: string, address: string) => {
openRequestModal();
await tezosRpc.testGetAccounts(chainId, address);
};
const onSignTransaction = async (chainId: string, address: string) => {
openRequestModal();
await tezosRpc.testSignTransaction(chainId, address);
};
const onSignMessage = async (chainId: string, address: string) => {
openRequestModal();
await tezosRpc.testSignMessage(chainId, address);
};
return [
{
method: DEFAULT_TEZOS_METHODS.TEZOS_GET_ACCOUNTS,
callback: onGetAccounts,
},
{
method: DEFAULT_TEZOS_METHODS.TEZOS_SEND,
callback: onSignTransaction,
},
{
method: DEFAULT_TEZOS_METHODS.TEZOS_SIGN,
callback: onSignMessage,
},
];
};
const getBlockchainActions = (chainId: string) => {
const [namespace] = chainId.split(":");
switch (namespace) {
@@ -323,6 +354,8 @@ const Home: NextPage = () => {
return getElrondActions();
case "tron":
return getTronActions();
case "tezos":
return getTezosActions();
default:
break;
}