Skip to content

Commit 53a2821

Browse files
feat: react-dapp-v2 updated for Tezos
Updated for Tezos: - fixed RPC calls - fixed modals for better user experience - added examples for contract calls, delegation, and more - added balance and token metadata
1 parent cbe3cbb commit 53a2821

File tree

12 files changed

+3459
-2822
lines changed

12 files changed

+3459
-2822
lines changed

Diff for: advanced/dapps/react-dapp-v2/package.json

+7-3
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,14 @@
55
"scripts": {
66
"dev": "next dev -p 3000",
77
"build": "next build",
8+
"clean": "rm -rf dist",
89
"start": "next start",
910
"lint": "next lint",
1011
"prettier": "prettier --check '**/*.{js,ts,jsx,tsx}'",
1112
"prettier:write": "prettier --write '**/*.{js,ts,jsx,tsx}'"
1213
},
1314
"dependencies": {
15+
"@airgap/beacon-types": "^4.2.2",
1416
"@celo/wallet-base": "^5.1.1",
1517
"@ethereumjs/tx": "^3.5.0",
1618
"@kadena/client": "^0.5.0",
@@ -20,6 +22,8 @@
2022
"@multiversx/sdk-wallet": "4.2.0",
2123
"@polkadot/util-crypto": "^10.1.2",
2224
"@solana/web3.js": "^1.36.0",
25+
"@taquito/rpc": "^20.0.1",
26+
"@taquito/taquito": "^20.0.1",
2327
"@walletconnect/encoding": "^1.0.1",
2428
"@walletconnect/sign-client": "2.15.2",
2529
"@walletconnect/types": "2.15.2",
@@ -52,14 +56,14 @@
5256
"@types/pino": "^7.0.5",
5357
"@types/prop-types": "^15.7.4",
5458
"@types/qr-image": "^3.2.5",
55-
"@types/react": "18.0.15",
56-
"@types/react-dom": "18.0.6",
59+
"@types/react": "^18.3.3",
60+
"@types/react-dom": "^18.3.0",
5761
"@types/styled-components": "^5.1.25",
5862
"eslint": "8.21.0",
5963
"eslint-config-next": "12.2.4",
6064
"eslint-plugin-package-json": "^0.13.1",
6165
"jsonc-eslint-parser": "^2.4.0",
6266
"prettier": "^2.8.8",
63-
"typescript": "^4.7.4"
67+
"typescript": "^5.5.4"
6468
}
6569
}

Diff for: advanced/dapps/react-dapp-v2/src/chains/tezos.ts

+4-2
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,16 @@ export const TezosChainData: ChainsMap = {
2222
mainnet: {
2323
name: "Tezos",
2424
id: "tezos:mainnet",
25-
rpc: ["https://mainnet.api.tez.ie"],
25+
rpc: ["https://rpc.tzbeta.net"],
26+
indexer: "https://api.tzkt.io/v1",
2627
slip44: 1729,
2728
testnet: false,
2829
},
2930
testnet: {
3031
name: "Tezos Testnet",
3132
id: "tezos:testnet",
32-
rpc: ["https://ghostnet.ecadinfra.com"],
33+
rpc: ["https://rpc.ghostnet.teztnets.com"],
34+
indexer: "https://api.ghostnet.tzkt.io/v1",
3335
slip44: 1729,
3436
testnet: true,
3537
},

Diff for: advanced/dapps/react-dapp-v2/src/components/Asset.tsx

+13-1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { getChainMetadata } from "../chains";
1010
const xdaiLogo = getChainMetadata("eip155:100").logo;
1111
const maticLogo = getChainMetadata("eip155:137").logo;
1212
const kadenaLogo = getChainMetadata("kadena:testnet04").logo;
13+
const tezosLogo = getChainMetadata("tezos:testnet").logo;
1314

1415
const SAsset = styled.div`
1516
width: 100%;
@@ -48,11 +49,22 @@ function getAssetIcon(asset: AssetData): JSX.Element {
4849
return <Icon src={maticLogo} />;
4950
case "kda":
5051
return <Icon src={kadenaLogo} />;
52+
case "xtz":
53+
return <Icon src={tezosLogo} />;
5154
default:
5255
return <Icon src={"/assets/eth20.svg"} />;
5356
}
5457
}
5558

59+
function getDecimals(asset: AssetData) : number {
60+
switch (asset?.symbol?.toLowerCase()) {
61+
case "xtz":
62+
return 6;
63+
default:
64+
return 18;
65+
}
66+
}
67+
5668
interface AssetProps {
5769
asset: AssetData;
5870
}
@@ -67,7 +79,7 @@ const Asset = (props: AssetProps) => {
6779
</SAssetLeft>
6880
<SAssetRight>
6981
<SAssetBalance>
70-
{fromWad(asset.balance || "0")} {asset.symbol}
82+
{fromWad(asset.balance || "0", getDecimals(asset))} {asset.symbol}
7183
</SAssetBalance>
7284
</SAssetRight>
7385
</SAsset>

Diff for: advanced/dapps/react-dapp-v2/src/components/Blockchain.tsx

+28
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,16 @@ const SBlockchainChildrenContainer = styled(SFullWidthContainer)`
8181
flex-direction: column;
8282
`;
8383

84+
const SPre = styled.div`
85+
background-color: #f4f4f4;
86+
width: 100%;
87+
min-width: 700px;
88+
textAlign: 'left';
89+
padding: 10px;
90+
border-radius: 5px;
91+
overflow-x: auto;
92+
`;
93+
8494
interface BlockchainProps {
8595
chainData: ChainNamespaces;
8696
fetching?: boolean;
@@ -126,6 +136,8 @@ const Blockchain: FC<PropsWithChildren<BlockchainProps>> = (
126136
balances,
127137
actions,
128138
} = props;
139+
const [hoveredDescription, setHoveredDescription] = React.useState<string | null>(null);
140+
129141
if (!Object.keys(chainData).length) return null;
130142

131143
const chain = getBlockchainDisplayData(chainId, chainData);
@@ -139,6 +151,15 @@ const Blockchain: FC<PropsWithChildren<BlockchainProps>> = (
139151
typeof account !== "undefined" && typeof balances !== "undefined"
140152
? balances[account]
141153
: [];
154+
155+
const handleActionHover = (description: string | undefined) => {
156+
if (description) {
157+
setHoveredDescription(JSON.stringify(description, null, 2));
158+
} else {
159+
setHoveredDescription(null);
160+
}
161+
};
162+
142163
return (
143164
<React.Fragment>
144165
<SAccount
@@ -181,6 +202,7 @@ const Blockchain: FC<PropsWithChildren<BlockchainProps>> = (
181202
left
182203
rgb={chain.meta.rgb}
183204
onClick={() => action.callback(chainId, address)}
205+
onMouseEnter={() => handleActionHover(action.description)}
184206
>
185207
{action.method}
186208
</SAction>
@@ -191,7 +213,13 @@ const Blockchain: FC<PropsWithChildren<BlockchainProps>> = (
191213
)}
192214
</SBlockchainChildrenContainer>
193215
</SAccount>
216+
{hoveredDescription && (
217+
<SPre>
218+
<pre style={{ textAlign: 'left' }}>{hoveredDescription}</pre>
219+
</SPre>
220+
)}
194221
</React.Fragment>
195222
);
196223
};
224+
197225
export default Blockchain;

Diff for: advanced/dapps/react-dapp-v2/src/constants/default.ts

+122
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,12 @@
11
import { getAppMetadata } from "@walletconnect/utils";
2+
import {
3+
PartialTezosDelegationOperation,
4+
PartialTezosIncreasePaidStorageOperation,
5+
PartialTezosOriginationOperation as PartialTezosOriginationOperationOriginal,
6+
PartialTezosTransactionOperation,
7+
TezosOperationType }
8+
from "@airgap/beacon-types";
9+
import { ScriptedContracts } from "@taquito/rpc";
210

311
if (!process.env.NEXT_PUBLIC_PROJECT_ID)
412
throw new Error("`NEXT_PUBLIC_PROJECT_ID` env variable is missing.");
@@ -244,11 +252,125 @@ export enum DEFAULT_TRON_EVENTS {}
244252
/**
245253
* TEZOS
246254
*/
255+
// Can be removed when the fix for Origination is released:
256+
// https://github.com/airgap-it/beacon-sdk/pull/806
257+
interface PartialTezosOriginationOperation
258+
extends Omit<PartialTezosOriginationOperationOriginal, "script"> {
259+
script: ScriptedContracts;
260+
}
261+
247262
export enum DEFAULT_TEZOS_METHODS {
248263
TEZOS_GET_ACCOUNTS = "tezos_getAccounts",
249264
TEZOS_SEND = "tezos_send",
250265
TEZOS_SIGN = "tezos_sign",
251266
}
267+
268+
export enum TEZOS_SAMPLE_KINDS {
269+
GET_ACCOUNTS = "tezos_getAccounts",
270+
SEND = "tezos_send",
271+
SEND_TRANSACTION = "tezos_send:transaction",
272+
SEND_ORGINATION = "tezos_send:origination",
273+
SEND_CONTRACT_CALL = "tezos_send:contract_call",
274+
SEND_DELEGATION = "tezos_send:delegation",
275+
SEND_UNDELEGATION = "tezos_send:undelegation",
276+
SEND_STAKE = "tezos_send:stake",
277+
SEND_UNSTAKE = "tezos_send:unstake",
278+
SEND_FINALIZE = "tezos_send:finalize",
279+
SEND_INCREASE_PAID_STORAGE = "tezos_send:increase_paid_storage",
280+
SIGN = "tezos_sign",
281+
}
282+
283+
const tezosTransactionOperation: PartialTezosTransactionOperation = {
284+
kind: TezosOperationType.TRANSACTION,
285+
destination: "tz3ZmB8oWUmi8YZXgeRpgAcPnEMD8VgUa4Ve", // Tezos Foundation Ghost Baker
286+
amount: "100000"
287+
};
288+
289+
const tezosOriginationOperation: PartialTezosOriginationOperation = {
290+
kind: TezosOperationType.ORIGINATION,
291+
balance: '1',
292+
script: { // This contract adds the parameter to the storage value
293+
code: [
294+
{ prim: "parameter", args: [{ prim: "int" }] },
295+
{ prim: "storage", args: [{ prim: "int" }] },
296+
{ prim: "code",
297+
args: [[
298+
{ prim: "DUP" }, // Duplicate the parameter (parameter is pushed onto the stack)
299+
{ prim: "CAR" }, // Access the parameter from the stack (parameter is on top)
300+
{ prim: "DIP", args: [[{ prim: "CDR" }]] }, // Access the storage value (storage is on the stack)
301+
{ prim: "ADD" }, // Add the parameter to the storage value
302+
{ prim: "NIL", args: [{ prim: "operation" }] }, // Create an empty list of operations
303+
{ prim: "PAIR" } // Pair the updated storage with the empty list of operations
304+
]]
305+
}
306+
],
307+
storage: { int: "10" }
308+
},
309+
};
310+
311+
const tezosContractCallOperation: PartialTezosTransactionOperation = {
312+
kind: TezosOperationType.TRANSACTION,
313+
destination: "[contract address]",
314+
amount: "0",
315+
parameters: { entrypoint: "default", value: { int: "20" } } // Add 20 to the current storage value
316+
};
317+
318+
const tezosDelegationOperation: PartialTezosDelegationOperation = {
319+
kind: TezosOperationType.DELEGATION,
320+
delegate: "tz3ZmB8oWUmi8YZXgeRpgAcPnEMD8VgUa4Ve" // Tezos Foundation Ghost Baker. Cannot delegate to ourself as that would block undelegation
321+
};
322+
323+
const tezosUndelegationOperation: PartialTezosDelegationOperation = {
324+
kind: TezosOperationType.DELEGATION
325+
};
326+
327+
const tezosStakeOperation: PartialTezosTransactionOperation = {
328+
kind: TezosOperationType.TRANSACTION,
329+
destination:"[own adress]",
330+
amount: "1000000",
331+
parameters: {
332+
entrypoint: "stake",
333+
value: { prim: "Unit" },
334+
},
335+
};
336+
337+
const tezosUnstakeOperation: PartialTezosTransactionOperation = {
338+
kind: TezosOperationType.TRANSACTION,
339+
destination:"[own adress]",
340+
amount: "1000000",
341+
parameters: {
342+
entrypoint: "unstake",
343+
value: { prim: "Unit" },
344+
},
345+
};
346+
347+
const tezosFinalizeOperation: PartialTezosTransactionOperation = {
348+
kind: TezosOperationType.TRANSACTION,
349+
destination:"[own adress]",
350+
amount: "0",
351+
parameters: {
352+
entrypoint: "finalize_unstake",
353+
value: { prim: "Unit" },
354+
},
355+
};
356+
357+
const TezosIncreasePaidStorageOperation: PartialTezosIncreasePaidStorageOperation = {
358+
kind: TezosOperationType.INCREASE_PAID_STORAGE,
359+
amount: "10",
360+
destination: "[contract address]"
361+
};
362+
363+
export const TEZOS_SAMPLES = {
364+
"tezos_send:transaction": tezosTransactionOperation,
365+
"tezos_send:origination": tezosOriginationOperation,
366+
"tezos_send:contract_call": tezosContractCallOperation,
367+
"tezos_send:delegation": tezosDelegationOperation,
368+
"tezos_send:undelegation": tezosUndelegationOperation,
369+
"tezos_send:stake": tezosStakeOperation,
370+
"tezos_send:unstake": tezosUnstakeOperation,
371+
"tezos_send:finalize": tezosFinalizeOperation,
372+
"tezos_send:increase_paid_storage": TezosIncreasePaidStorageOperation,
373+
};
252374

253375
export enum DEFAULT_TEZOS_EVENTS {}
254376

0 commit comments

Comments
 (0)