Skip to content

Commit

Permalink
Merge pull request #191 from ton-blockchain/semichain_support
Browse files Browse the repository at this point in the history
Semichain support + invalid admin address bugfix + async jetton wallet load bugfix
  • Loading branch information
EmelyanenkoK authored Jun 24, 2024
2 parents c877b79 + a6b8086 commit 2bf9b3b
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 35 deletions.
40 changes: 29 additions & 11 deletions src/lib/jetton-minter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ export type JettonMetaDataKeys =
| "image"
| "symbol"
| "image_data"
| "decimals";
| "decimals"
| "uri";

const jettonOnChainMetadataSpec: {
[key in JettonMetaDataKeys]: "utf8" | "ascii" | undefined;
Expand All @@ -40,6 +41,7 @@ const jettonOnChainMetadataSpec: {
decimals: "utf8",
symbol: "utf8",
image_data: undefined,
uri: "ascii",
};

const sha256 = (str: string) => {
Expand Down Expand Up @@ -88,27 +90,42 @@ export function buildJettonOffChainMetadata(contentUri: string): Cell {
.endCell();
}

export type persistenceType = "onchain" | "offchain_private_domain" | "offchain_ipfs";
export type PersistenceType = "onchain" | "offchain_private_domain" | "offchain_ipfs";

export async function readJettonMetadata(contentCell: Cell): Promise<{
persistenceType: persistenceType;
persistenceType: PersistenceType;
metadata: { [s in JettonMetaDataKeys]?: string };
isJettonDeployerFaultyOnChainData?: boolean;
}> {
const contentSlice = contentCell.beginParse();

switch (contentSlice.readUint(8).toNumber()) {
case ONCHAIN_CONTENT_PREFIX:
case ONCHAIN_CONTENT_PREFIX: {
const res = parseJettonOnchainMetadata(contentSlice);

let persistenceType: PersistenceType = "onchain";

if (res.metadata.uri) {
const offchainMetadata = await getJettonMetadataFromExternalUri(res.metadata.uri);
persistenceType = offchainMetadata.isIpfs ? "offchain_ipfs" : "offchain_private_domain";
res.metadata = {
...res.metadata,
...offchainMetadata.metadata,
};
}

return {
persistenceType: "onchain",
...parseJettonOnchainMetadata(contentSlice),
persistenceType: persistenceType,
...res,
};
case OFFCHAIN_CONTENT_PREFIX:
}
case OFFCHAIN_CONTENT_PREFIX: {
const { metadata, isIpfs } = await parseJettonOffchainMetadata(contentSlice);
return {
persistenceType: isIpfs ? "offchain_ipfs" : "offchain_private_domain",
metadata,
};
}
default:
throw new Error("Unexpected jetton metadata content prefix");
}
Expand All @@ -118,10 +135,11 @@ async function parseJettonOffchainMetadata(contentSlice: Slice): Promise<{
metadata: { [s in JettonMetaDataKeys]?: string };
isIpfs: boolean;
}> {
const jsonURI = contentSlice
.readRemainingBytes()
.toString("ascii")
.replace("ipfs://", "https://ipfs.io/ipfs/");
return getJettonMetadataFromExternalUri(contentSlice.readRemainingBytes().toString("ascii"));
}

async function getJettonMetadataFromExternalUri(uri: string) {
const jsonURI = uri.replace("ipfs://", "https://ipfs.io/ipfs/");

return {
metadata: (await axios.get(jsonURI)).data,
Expand Down
18 changes: 7 additions & 11 deletions src/pages/jetton/index.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,15 @@
import { useTonAddress } from "@tonconnect/ui-react";
import { Screen, ScreenContent } from "components/Screen";
import { useJettonAddress } from "hooks/useJettonAddress";
import useNotification from "hooks/useNotification";
import { Token } from "pages/jetton/dataRow/token";
import { StyledContainer } from "pages/jetton/styled";
import { Wallet } from "pages/jetton/wallet";
import { useEffect } from "react";
import { ScreenContent, Screen } from "components/Screen";
import useJettonStore from "store/jetton-store/useJettonStore";
import FaultyDeploy from "./FaultyDeploy";
import { StyledContainer } from "pages/jetton/styled";
import { Wallet } from "pages/jetton/wallet";
import { Token } from "pages/jetton/dataRow/token";
import { Typography } from "@mui/material";
import { useRecoilValue } from "recoil";
import { jettonActionsState } from "pages/jetton/actions/jettonActions";
import { useJettonAddress } from "hooks/useJettonAddress";
import useNotification from "hooks/useNotification";
import { useTonAddress } from "@tonconnect/ui-react";

export const Jetton = () => {
const actionInProgress = useRecoilValue(jettonActionsState);
const { getJettonDetails } = useJettonStore();
const { isAddressEmpty, jettonAddress } = useJettonAddress();
const { showNotification } = useNotification();
Expand Down
6 changes: 3 additions & 3 deletions src/pages/jetton/util.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { persistenceType } from "lib/jetton-minter";
import { PersistenceType } from "lib/jetton-minter";
import BurnJettonsAction from "./actions/BurnJettonsAction";
import MintJettonsAction from "./actions/MintJettonsAction";
import RevokeOwnershipAction from "./actions/RevokeOwnershipAction";
Expand Down Expand Up @@ -55,7 +55,7 @@ export const getAdminMessage = (
};

export const getMetadataWarning = (
persistenceType?: persistenceType,
persistenceType?: PersistenceType,
adminRevokedOwnership?: boolean,
): JettonDetailMessage | undefined => {
if (persistenceType === "onchain" && !adminRevokedOwnership) {
Expand All @@ -82,7 +82,7 @@ export const getMetadataWarning = (
};

export const getTotalSupplyWarning = (
persistenceType?: persistenceType,
persistenceType?: PersistenceType,
adminRevokedOwnership?: boolean,
): JettonDetailMessage | undefined => {
if (persistenceType === "onchain" && !adminRevokedOwnership) {
Expand Down
4 changes: 2 additions & 2 deletions src/store/jetton-store/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import BN from "bn.js";
import { persistenceType } from "lib/jetton-minter";
import { PersistenceType } from "lib/jetton-minter";
import { atom } from "recoil";

export interface JettonStoreState {
Expand All @@ -14,7 +14,7 @@ export interface JettonStoreState {
adminAddress?: string;
balance?: BN;
jettonMaster?: string;
persistenceType?: persistenceType;
persistenceType?: PersistenceType;
totalSupply?: BN;
jettonWalletAddress?: string;
isJettonDeployerFaultyOnChainData?: boolean;
Expand Down
26 changes: 18 additions & 8 deletions src/store/jetton-store/useJettonStore.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
import { useTonAddress } from "@tonconnect/ui-react";
import QuestiomMarkImg from "assets/icons/question.png";
import { useJettonAddress } from "hooks/useJettonAddress";
import useNotification from "hooks/useNotification";
import { jettonDeployController } from "lib/deploy-controller";
import { zeroAddress } from "lib/utils";
import { useCallback } from "react";
import { useRecoilState, useResetRecoilState } from "recoil";
import { Address } from "ton";
import { jettonStateAtom } from ".";
import QuestiomMarkImg from "assets/icons/question.png";
import { useCallback } from "react";
import useNotification from "hooks/useNotification";
import { getUrlParam, isValidAddress } from "utils";
import { useJettonAddress } from "hooks/useJettonAddress";
import { useTonAddress, useTonConnectUI } from "@tonconnect/ui-react";
import { jettonStateAtom } from ".";

let i = 0;

function useJettonStore() {
const [state, setState] = useRecoilState(jettonStateAtom);
Expand All @@ -18,6 +20,9 @@ function useJettonStore() {
const { jettonAddress } = useJettonAddress();

const getJettonDetails = useCallback(async () => {
i++;
const myIndex = i;

let queryAddress = getUrlParam("address");

if (queryAddress && !isValidAddress(queryAddress)) {
Expand All @@ -27,6 +32,7 @@ function useJettonStore() {
}

const address = queryAddress || connectedWalletAddress;

const isMyWallet = address ? address === connectedWalletAddress : false;

reset();
Expand Down Expand Up @@ -54,7 +60,7 @@ function useJettonStore() {

return;
}
const _adminAddress = result.minter.admin.toFriendly();
const _adminAddress = result.minter.admin?.toFriendly() ?? zeroAddress().toFriendly();
const admin = isMyWallet && _adminAddress === connectedWalletAddress;

let image: string | undefined;
Expand Down Expand Up @@ -87,6 +93,9 @@ function useJettonStore() {
}
}

if (myIndex !== i) {
return;
}
setState((prevState) => {
return {
...prevState,
Expand All @@ -102,14 +111,15 @@ function useJettonStore() {
decimals: result.minter.metadata.decimals || "9",
adminAddress: _adminAddress,
balance: result.jettonWallet ? result.jettonWallet.balance : undefined,
jettonWalletAddress: result.jettonWallet?.jWalletAddress.toFriendly(),
jettonWalletAddress: result.jettonWallet?.jWalletAddress?.toFriendly(),
jettonMaster: jettonAddress,
isMyWallet,
selectedWalletAddress: address,
};
});
} catch (error) {
if (error instanceof Error) {
console.error(error);
showNotification(
!!error.message.match(/exit_code: (11|32)/g)
? `Unable to query. This is probably not a Jetton Contract (${error.message})`
Expand Down

0 comments on commit 2bf9b3b

Please sign in to comment.