From 24000515f87353adf8b55f0591396ece79b97ca7 Mon Sep 17 00:00:00 2001 From: Gusarich Date: Tue, 4 Apr 2023 17:46:21 +0300 Subject: [PATCH 01/30] add migration button for minters with old code --- src/lib/deploy-controller.ts | 6 ++++++ src/pages/jetton/dataRow/token/Token.tsx | 17 +++++++++++++++++ src/store/jetton-store/index.ts | 2 ++ src/store/jetton-store/useJettonStore.ts | 8 +++++++- 4 files changed, 32 insertions(+), 1 deletion(-) diff --git a/src/lib/deploy-controller.ts b/src/lib/deploy-controller.ts index e05f5dd..eade0ab 100644 --- a/src/lib/deploy-controller.ts +++ b/src/lib/deploy-controller.ts @@ -209,6 +209,12 @@ class JettonDeployController { }; } + async getJettonMinterCode(contractAddress: Address) { + const client = getClient(); + const code = (await (await client).getContractState(contractAddress)).code!; + return code; + } + async fixFaultyJetton( contractAddress: Address, data: { diff --git a/src/pages/jetton/dataRow/token/Token.tsx b/src/pages/jetton/dataRow/token/Token.tsx index 5080d6d..04ec9bf 100644 --- a/src/pages/jetton/dataRow/token/Token.tsx +++ b/src/pages/jetton/dataRow/token/Token.tsx @@ -45,6 +45,7 @@ export const Token = () => { jettonLoading, decimals, isImageBroken, + isCodeOld, } = useJettonStore(); const [openEdit, setOpenEdit] = useState(false); @@ -103,6 +104,22 @@ export const Token = () => { )} + {isCodeOld && !jettonLoading && ( + + setOpenEdit(true)}> + + Pen Icon + Migration + + + + )} {!isAdmin && isJettonDeployerFaultyOnChainData && ( diff --git a/src/store/jetton-store/index.ts b/src/store/jetton-store/index.ts index 8395480..b150fc8 100644 --- a/src/store/jetton-store/index.ts +++ b/src/store/jetton-store/index.ts @@ -21,6 +21,7 @@ export interface JettonStoreState { jettonLoading: boolean; isMyWallet: boolean; selectedWalletAddress?: string | null; + isCodeOld: boolean; } const jettonStateAtom = atom({ @@ -44,6 +45,7 @@ const jettonStateAtom = atom({ isJettonDeployerFaultyOnChainData: false, isMyWallet: false, selectedWalletAddress: undefined, + isCodeOld: false, }, }); diff --git a/src/store/jetton-store/useJettonStore.ts b/src/store/jetton-store/useJettonStore.ts index db29e36..472b9ba 100644 --- a/src/store/jetton-store/useJettonStore.ts +++ b/src/store/jetton-store/useJettonStore.ts @@ -3,7 +3,7 @@ import { jettonDeployController } from "lib/deploy-controller"; import { zeroAddress } from "lib/utils"; import { useRecoilState, useResetRecoilState } from "recoil"; import WalletConnection from "services/wallet-connection"; -import { Address } from "ton"; +import { Address, Cell } from "ton"; import { jettonStateAtom } from "."; import QuestiomMarkImg from "assets/icons/question.png"; import { useCallback } from "react"; @@ -11,6 +11,7 @@ import useNotification from "hooks/useNotification"; import useConnectionStore from "store/connection-store/useConnectionStore"; import { getUrlParam, isValidAddress } from "utils"; import { useJettonAddress } from "hooks/useJettonAddress"; +import { JETTON_MINTER_CODE } from "lib/jetton-minter"; function useJettonStore() { const [state, setState] = useRecoilState(jettonStateAtom); @@ -98,6 +99,10 @@ function useJettonStore() { } } + const minterCode = Cell.fromBoc( + await jettonDeployController.getJettonMinterCode(parsedJettonMaster), + )[0]; + setState((prevState) => { return { ...prevState, @@ -117,6 +122,7 @@ function useJettonStore() { jettonMaster: jettonAddress, isMyWallet, selectedWalletAddress: address, + isCodeOld: !minterCode.equals(JETTON_MINTER_CODE), }; }); } catch (error) { From fa0ec5e2818422fc733e18721d3fddf8f4c57980 Mon Sep 17 00:00:00 2001 From: Gusarich Date: Thu, 6 Apr 2023 10:57:13 +0300 Subject: [PATCH 02/30] migration popup window --- src/pages/jetton/dataRow/token/Token.tsx | 41 ++++++++----- src/pages/jetton/migration.tsx | 74 ++++++++++++++++++++++++ 2 files changed, 99 insertions(+), 16 deletions(-) create mode 100644 src/pages/jetton/migration.tsx diff --git a/src/pages/jetton/dataRow/token/Token.tsx b/src/pages/jetton/dataRow/token/Token.tsx index 04ec9bf..e0276ad 100644 --- a/src/pages/jetton/dataRow/token/Token.tsx +++ b/src/pages/jetton/dataRow/token/Token.tsx @@ -27,6 +27,7 @@ import brokenImage from "assets/icons/question.png"; import { AppButton } from "components/appButton"; import pen from "assets/icons/pen.svg"; import { CenteringWrapper } from "components/footer/styled"; +import { MigrationPopup } from "pages/jetton/migration"; export const Token = () => { const { @@ -48,6 +49,11 @@ export const Token = () => { isCodeOld, } = useJettonStore(); const [openEdit, setOpenEdit] = useState(false); + const [openMigration, setOpenMigration] = useState(false); + + const handleMigrationClick = () => { + setOpenMigration(!openMigration); + }; return ( @@ -104,22 +110,25 @@ export const Token = () => { )} - {isCodeOld && !jettonLoading && ( - - setOpenEdit(true)}> - - Pen Icon - Migration - - - - )} + + { + /* isAdmin && */ isCodeOld && !jettonLoading && ( + + + + Pen Icon + Migration + + + + ) + } {!isAdmin && isJettonDeployerFaultyOnChainData && ( diff --git a/src/pages/jetton/migration.tsx b/src/pages/jetton/migration.tsx new file mode 100644 index 0000000..3eacceb --- /dev/null +++ b/src/pages/jetton/migration.tsx @@ -0,0 +1,74 @@ +import useJettonStore from "store/jetton-store/useJettonStore"; +import { AppButton } from "components/appButton"; +import { CenteringWrapper } from "components/footer/styled"; +import { Popup } from "components/Popup"; +import { Typography } from "@mui/material"; +import bullet from "assets/icons/bullet.svg"; +import { Box } from "@mui/system"; + +export const MigrationPopup = ({ open, onClose }: { open: boolean; onClose: () => void }) => { + const { symbol } = useJettonStore(); + + const onSubmit = () => { + console.log("onSubmit"); + onClose(); + }; + + return ( + + + + Initiate migration + + + This operation will initiate the migration process of the
token{" "} + {symbol}. This means: +
+
    +
  • + + New Jetton contract will be deployed with the same settings + +
  • +
  • + + Users will need to migrate their {symbol}{" "} + manually{" "} + +
  • +
  • + + Your project should support the new version of the Jetton + +
  • +
+ + You should consider these points before initiating the migration. + +
+ + + onClose()}> + Cancel + + + + Migration + + +
+ ); +}; From e2dac6d0655a4fb6373bc3e5d859f6f31b43cddc Mon Sep 17 00:00:00 2001 From: Gusarich Date: Thu, 6 Apr 2023 11:21:01 +0300 Subject: [PATCH 03/30] update migrationpopup --- src/pages/jetton/dataRow/token/Token.tsx | 14 +++++++------- src/pages/jetton/migration.tsx | 24 ++++++++++++++++++++---- 2 files changed, 27 insertions(+), 11 deletions(-) diff --git a/src/pages/jetton/dataRow/token/Token.tsx b/src/pages/jetton/dataRow/token/Token.tsx index e0276ad..1500507 100644 --- a/src/pages/jetton/dataRow/token/Token.tsx +++ b/src/pages/jetton/dataRow/token/Token.tsx @@ -49,11 +49,7 @@ export const Token = () => { isCodeOld, } = useJettonStore(); const [openEdit, setOpenEdit] = useState(false); - const [openMigration, setOpenMigration] = useState(false); - - const handleMigrationClick = () => { - setOpenMigration(!openMigration); - }; + const [openMigrationPopup, setOpenMigrationPopup] = useState(false); return ( @@ -110,11 +106,15 @@ export const Token = () => { )} - + { /* isAdmin && */ isCodeOld && !jettonLoading && ( - + setOpenMigrationPopup(true)}> void }) => { +export function MigrationPopup({ + open, + setOpen, +}: { + open: boolean; + setOpen: (arg0: boolean) => void; +}) { const { symbol } = useJettonStore(); + const onClose = () => { + setOpen(false); + }; + const onSubmit = () => { - console.log("onSubmit"); onClose(); + console.log(123); }; return ( @@ -65,10 +76,15 @@ export const MigrationPopup = ({ open, onClose }: { open: boolean; onClose: () = Cancel - + { + onClose(); + onSubmit(); + }}> Migration ); -}; +} From 2adfb7e54c6617324e87e36b3b8e0fb307fd1412 Mon Sep 17 00:00:00 2001 From: Gusarich Date: Sun, 21 May 2023 11:52:05 +0300 Subject: [PATCH 04/30] add loading window after clicking "Migrate" --- src/pages/jetton/migration.tsx | 178 ++++++++++++++++++++++----------- 1 file changed, 118 insertions(+), 60 deletions(-) diff --git a/src/pages/jetton/migration.tsx b/src/pages/jetton/migration.tsx index 7dd55b9..af938c4 100644 --- a/src/pages/jetton/migration.tsx +++ b/src/pages/jetton/migration.tsx @@ -6,6 +6,8 @@ import { Typography } from "@mui/material"; import bullet from "assets/icons/bullet.svg"; import { Box } from "@mui/system"; import { useState } from "react"; +import CircularProgress from "@mui/material/CircularProgress"; +import CheckCircleIcon from "@mui/icons-material/CheckCircle"; export function MigrationPopup({ open, @@ -15,76 +17,132 @@ export function MigrationPopup({ setOpen: (arg0: boolean) => void; }) { const { symbol } = useJettonStore(); + const [progress, setProgress] = useState([false, false, false]); + const [migrationStarted, setMigrationStarted] = useState(false); const onClose = () => { setOpen(false); }; const onSubmit = () => { - onClose(); - console.log(123); + setMigrationStarted(true); + setTimeout(() => sendTransaction(0), 1300); + setTimeout(() => sendTransaction(1), 2600); + setTimeout(() => sendTransaction(2), 3900); + }; + + const sendTransaction = async (index: number) => { + // Simulate sending a transaction + await new Promise((resolve) => setTimeout(resolve, 1000)); + + // Update the progress state + setProgress((prevProgress) => { + const newProgress = [...prevProgress]; + newProgress[index] = true; + return newProgress; + }); }; return ( - - - Initiate migration - - - This operation will initiate the migration process of the
token{" "} - {symbol}. This means: -
-
    -
  • - - New Jetton contract will be deployed with the same settings - -
  • -
  • - - Users will need to migrate their {symbol}{" "} - manually{" "} - -
  • -
  • - - Your project should support the new version of the Jetton - -
  • -
- - You should consider these points before initiating the migration. - -
- - - onClose()}> - Cancel - - - { - onClose(); - onSubmit(); - }}> - Migration - - + {!migrationStarted ? ( + <> + + + Initiate migration + + + This operation will initiate the migration process of the
token{" "} + {symbol}. This means: +
+
    +
  • + + New Jetton contract will be deployed with the same settings + +
  • +
  • + + Users will need to migrate their {symbol}{" "} + manually{" "} + +
  • +
  • + + Your project should support the new version of the Jetton + +
  • +
+ + You should consider these points before initiating the migration. + +
+ + + onClose()}> + Cancel + + + { + onSubmit(); + }}> + Migration + + + + ) : ( + + )}
); } +function TransactionProgress({ progress }: { progress: boolean[] }) { + return ( +
+ + Migration process + + + + Do not close this page until you finish the process. + + + {progress.map((done, index) => ( + + + Transaction {index + 1} + + ))} +
+ ); +} + +function Spinner({ spinning }: { spinning: boolean }) { + return ( + + {spinning ? : } + + ); +} From 80150fec13bbfa3aeccf0facce2f9bfec8c90628 Mon Sep 17 00:00:00 2001 From: Gusarich Date: Sun, 21 May 2023 12:13:56 +0300 Subject: [PATCH 05/30] add redirect via button after success --- src/pages/jetton/migration.tsx | 35 ++++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/src/pages/jetton/migration.tsx b/src/pages/jetton/migration.tsx index af938c4..43bd013 100644 --- a/src/pages/jetton/migration.tsx +++ b/src/pages/jetton/migration.tsx @@ -8,6 +8,7 @@ import { Box } from "@mui/system"; import { useState } from "react"; import CircularProgress from "@mui/material/CircularProgress"; import CheckCircleIcon from "@mui/icons-material/CheckCircle"; +import { useNavigate } from "react-router-dom"; export function MigrationPopup({ open, @@ -19,6 +20,9 @@ export function MigrationPopup({ const { symbol } = useJettonStore(); const [progress, setProgress] = useState([false, false, false]); const [migrationStarted, setMigrationStarted] = useState(false); + const [showRedirectButton, setShowRedirectButton] = useState(false); + + const navigate = useNavigate(); const onClose = () => { setOpen(false); @@ -41,6 +45,16 @@ export function MigrationPopup({ newProgress[index] = true; return newProgress; }); + + // If this is the last transaction, show the redirect button + if (index === 2) { + setShowRedirectButton(true); + } + }; + + const redirectToNewPage = () => { + const newJettonAddress = "EQAGPPuLtcu8BimtY8TFVrpJ-E36akEFZHexCSD_BNQl_QrW"; + navigate(`/jetton/${newJettonAddress}`); }; return ( @@ -106,11 +120,24 @@ export function MigrationPopup({ ) : ( - + <> + + {showRedirectButton && ( + { + onClose(); + redirectToNewPage(); + }}> + Go to the new Jetton + + )} + )} ); } + function TransactionProgress({ progress }: { progress: boolean[] }) { return (
@@ -130,7 +157,11 @@ function TransactionProgress({ progress }: { progress: boolean[] }) { {progress.map((done, index) => ( - + Transaction {index + 1} From 3ad9442710445411477fd3f5578d0d0494319241 Mon Sep 17 00:00:00 2001 From: Gusarich Date: Sun, 21 May 2023 17:35:32 +0300 Subject: [PATCH 06/30] split `sendTransaction` into three separate functions --- src/pages/jetton/migration.tsx | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/src/pages/jetton/migration.tsx b/src/pages/jetton/migration.tsx index 43bd013..4a5ccc1 100644 --- a/src/pages/jetton/migration.tsx +++ b/src/pages/jetton/migration.tsx @@ -35,9 +35,26 @@ export function MigrationPopup({ setTimeout(() => sendTransaction(2), 3900); }; + const deployNewJetton = async () => {}; + + const deployMigrationMaster = async () => {}; + + const mintJettonsToMaster = async () => {}; + const sendTransaction = async (index: number) => { - // Simulate sending a transaction - await new Promise((resolve) => setTimeout(resolve, 1000)); + switch (index) { + case 0: + await deployNewJetton(); + break; + case 1: + await deployMigrationMaster(); + break; + case 2: + await mintJettonsToMaster(); + break; + default: + break; + } // Update the progress state setProgress((prevProgress) => { From 9066dcadd56c563dabc5d7c7993af00a2c220843 Mon Sep 17 00:00:00 2001 From: Gusarich Date: Sun, 21 May 2023 18:02:32 +0300 Subject: [PATCH 07/30] add `isNewMinterDeployed`, `isMigrationMasterDeployed` and `mintedJettonsToMaster` states --- src/pages/jetton/migration.tsx | 110 ++++++++++++----------- src/store/jetton-store/index.ts | 8 ++ src/store/jetton-store/useJettonStore.ts | 52 +++++++++++ 3 files changed, 117 insertions(+), 53 deletions(-) diff --git a/src/pages/jetton/migration.tsx b/src/pages/jetton/migration.tsx index 4a5ccc1..f7e2cac 100644 --- a/src/pages/jetton/migration.tsx +++ b/src/pages/jetton/migration.tsx @@ -5,7 +5,6 @@ import { Popup } from "components/Popup"; import { Typography } from "@mui/material"; import bullet from "assets/icons/bullet.svg"; import { Box } from "@mui/system"; -import { useState } from "react"; import CircularProgress from "@mui/material/CircularProgress"; import CheckCircleIcon from "@mui/icons-material/CheckCircle"; import { useNavigate } from "react-router-dom"; @@ -17,10 +16,17 @@ export function MigrationPopup({ open: boolean; setOpen: (arg0: boolean) => void; }) { - const { symbol } = useJettonStore(); - const [progress, setProgress] = useState([false, false, false]); - const [migrationStarted, setMigrationStarted] = useState(false); - const [showRedirectButton, setShowRedirectButton] = useState(false); + const { + symbol, + isNewMinterDeployed, + isMigrationMasterDeployed, + mintedJettonsToMaster, + migrationStarted, + setNewMinterDeployed, + setMigrationMasterDeployed, + setMintedJettonsToMaster, + setMigrationStarted, + } = useJettonStore(); const navigate = useNavigate(); @@ -35,11 +41,17 @@ export function MigrationPopup({ setTimeout(() => sendTransaction(2), 3900); }; - const deployNewJetton = async () => {}; + const deployNewJetton = async () => { + setNewMinterDeployed(true); + }; - const deployMigrationMaster = async () => {}; + const deployMigrationMaster = async () => { + setMigrationMasterDeployed(true); + }; - const mintJettonsToMaster = async () => {}; + const mintJettonsToMaster = async () => { + setMintedJettonsToMaster(true); + }; const sendTransaction = async (index: number) => { switch (index) { @@ -55,19 +67,43 @@ export function MigrationPopup({ default: break; } + }; - // Update the progress state - setProgress((prevProgress) => { - const newProgress = [...prevProgress]; - newProgress[index] = true; - return newProgress; - }); + function TransactionProgress() { + return ( +
+ + Migration process + + + + Do not close this page until you finish the process. + + + + + Deploy new Jetton Minter + - // If this is the last transaction, show the redirect button - if (index === 2) { - setShowRedirectButton(true); - } - }; + + + Deploy the Migration Master + + + + + Mint tokens to the Migration Master + +
+ ); + } const redirectToNewPage = () => { const newJettonAddress = "EQAGPPuLtcu8BimtY8TFVrpJ-E36akEFZHexCSD_BNQl_QrW"; @@ -138,8 +174,8 @@ export function MigrationPopup({ ) : ( <> - - {showRedirectButton && ( + + {isNewMinterDeployed && isMigrationMasterDeployed && mintedJettonsToMaster && ( { @@ -155,38 +191,6 @@ export function MigrationPopup({ ); } -function TransactionProgress({ progress }: { progress: boolean[] }) { - return ( -
- - Migration process - - - - Do not close this page until you finish the process. - - - {progress.map((done, index) => ( - - - Transaction {index + 1} - - ))} -
- ); -} - function Spinner({ spinning }: { spinning: boolean }) { return ( diff --git a/src/store/jetton-store/index.ts b/src/store/jetton-store/index.ts index b150fc8..f8908c0 100644 --- a/src/store/jetton-store/index.ts +++ b/src/store/jetton-store/index.ts @@ -22,6 +22,10 @@ export interface JettonStoreState { isMyWallet: boolean; selectedWalletAddress?: string | null; isCodeOld: boolean; + isNewMinterDeployed: boolean; + isMigrationMasterDeployed: boolean; + mintedJettonsToMaster: boolean; + migrationStarted: boolean; } const jettonStateAtom = atom({ @@ -46,6 +50,10 @@ const jettonStateAtom = atom({ isMyWallet: false, selectedWalletAddress: undefined, isCodeOld: false, + isNewMinterDeployed: false, + isMigrationMasterDeployed: false, + mintedJettonsToMaster: false, + migrationStarted: false, }, }); diff --git a/src/store/jetton-store/useJettonStore.ts b/src/store/jetton-store/useJettonStore.ts index 472b9ba..3a7dd84 100644 --- a/src/store/jetton-store/useJettonStore.ts +++ b/src/store/jetton-store/useJettonStore.ts @@ -20,6 +20,46 @@ function useJettonStore() { const { address: connectedWalletAddress } = useConnectionStore(); const { jettonAddress } = useJettonAddress(); + const setNewMinterDeployed = useCallback( + (newValue: boolean) => { + setState((prevState) => ({ + ...prevState, + isNewMinterDeployed: newValue, + })); + }, + [setState], + ); + + const setMigrationMasterDeployed = useCallback( + (newValue: boolean) => { + setState((prevState) => ({ + ...prevState, + isMigrationMasterDeployed: newValue, + })); + }, + [setState], + ); + + const setMintedJettonsToMaster = useCallback( + (newValue: boolean) => { + setState((prevState) => ({ + ...prevState, + mintedJettonsToMaster: newValue, + })); + }, + [setState], + ); + + const setMigrationStarted = useCallback( + (newValue: boolean) => { + setState((prevState) => ({ + ...prevState, + migrationStarted: newValue, + })); + }, + [setState], + ); + const getJettonDetails = useCallback(async () => { let queryAddress = getUrlParam("address"); @@ -103,6 +143,10 @@ function useJettonStore() { await jettonDeployController.getJettonMinterCode(parsedJettonMaster), )[0]; + const isNewMinterDeployed = false; // TODO + const isMigrationMasterDeployed = false; // TODO + const mintedJettonsToMaster = false; // TODO + setState((prevState) => { return { ...prevState, @@ -123,6 +167,10 @@ function useJettonStore() { isMyWallet, selectedWalletAddress: address, isCodeOld: !minterCode.equals(JETTON_MINTER_CODE), + isNewMinterDeployed, + isMigrationMasterDeployed, + mintedJettonsToMaster, + migrationStarted: false, }; }); } catch (error) { @@ -146,6 +194,10 @@ function useJettonStore() { ...state, getJettonDetails, reset, + setNewMinterDeployed, + setMigrationMasterDeployed, + setMintedJettonsToMaster, + setMigrationStarted, }; } From 0aad937df2d75c19971de1ee4732e4ee6536f139 Mon Sep 17 00:00:00 2001 From: Gusarich Date: Sun, 21 May 2023 18:17:15 +0300 Subject: [PATCH 08/30] refactor the code --- src/pages/jetton/migration.tsx | 67 ++++++++++++++++------------------ 1 file changed, 32 insertions(+), 35 deletions(-) diff --git a/src/pages/jetton/migration.tsx b/src/pages/jetton/migration.tsx index f7e2cac..978d487 100644 --- a/src/pages/jetton/migration.tsx +++ b/src/pages/jetton/migration.tsx @@ -34,42 +34,44 @@ export function MigrationPopup({ setOpen(false); }; - const onSubmit = () => { + const onSubmit = async () => { setMigrationStarted(true); - setTimeout(() => sendTransaction(0), 1300); - setTimeout(() => sendTransaction(1), 2600); - setTimeout(() => sendTransaction(2), 3900); + await deployNewJetton(); + await deployMigrationMaster(); + await mintJettonsToMaster(); }; const deployNewJetton = async () => { + // TODO + await new Promise((r) => setTimeout(r, 1000)); setNewMinterDeployed(true); }; const deployMigrationMaster = async () => { + // TODO + await new Promise((r) => setTimeout(r, 1000)); setMigrationMasterDeployed(true); }; const mintJettonsToMaster = async () => { + // TODO + await new Promise((r) => setTimeout(r, 1000)); setMintedJettonsToMaster(true); }; - const sendTransaction = async (index: number) => { - switch (index) { - case 0: - await deployNewJetton(); - break; - case 1: - await deployMigrationMaster(); - break; - case 2: - await mintJettonsToMaster(); - break; - default: - break; - } - }; + interface TransactionStepProps { + spinning: boolean; + description: string; + } + + const TransactionStep: React.FC = ({ spinning, description }) => ( + + + {description} + + ); - function TransactionProgress() { + const TransactionProgress = () => { return (
- - - Deploy new Jetton Minter - - - - - Deploy the Migration Master - - - - - Mint tokens to the Migration Master - + + +
); - } + }; const redirectToNewPage = () => { const newJettonAddress = "EQAGPPuLtcu8BimtY8TFVrpJ-E36akEFZHexCSD_BNQl_QrW"; From 9c3189e0d0c3c591278c8d39a187221629574f45 Mon Sep 17 00:00:00 2001 From: Gusarich Date: Sun, 21 May 2023 18:23:24 +0300 Subject: [PATCH 09/30] add possibility to resume --- src/pages/jetton/migration.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/pages/jetton/migration.tsx b/src/pages/jetton/migration.tsx index 978d487..1d88faa 100644 --- a/src/pages/jetton/migration.tsx +++ b/src/pages/jetton/migration.tsx @@ -36,9 +36,9 @@ export function MigrationPopup({ const onSubmit = async () => { setMigrationStarted(true); - await deployNewJetton(); - await deployMigrationMaster(); - await mintJettonsToMaster(); + if (!isNewMinterDeployed) await deployNewJetton(); + if (!isMigrationMasterDeployed) await deployMigrationMaster(); + if (!mintedJettonsToMaster) await mintJettonsToMaster(); }; const deployNewJetton = async () => { From 425b478e6a7b27a228c2d26b00a26f1e1149b36a Mon Sep 17 00:00:00 2001 From: Gusarich Date: Sun, 21 May 2023 18:27:49 +0300 Subject: [PATCH 10/30] add connection check --- src/pages/jetton/migration.tsx | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/pages/jetton/migration.tsx b/src/pages/jetton/migration.tsx index 1d88faa..5943d9d 100644 --- a/src/pages/jetton/migration.tsx +++ b/src/pages/jetton/migration.tsx @@ -8,6 +8,8 @@ import { Box } from "@mui/system"; import CircularProgress from "@mui/material/CircularProgress"; import CheckCircleIcon from "@mui/icons-material/CheckCircle"; import { useNavigate } from "react-router-dom"; +import WalletConnection from "services/wallet-connection"; +import useConnectionStore from "store/connection-store/useConnectionStore"; export function MigrationPopup({ open, @@ -27,6 +29,7 @@ export function MigrationPopup({ setMintedJettonsToMaster, setMigrationStarted, } = useJettonStore(); + const { address } = useConnectionStore(); const navigate = useNavigate(); @@ -35,6 +38,10 @@ export function MigrationPopup({ }; const onSubmit = async () => { + const connection = WalletConnection.getConnection(); + if (!address || !connection) { + throw new Error("Wallet not connected"); + } setMigrationStarted(true); if (!isNewMinterDeployed) await deployNewJetton(); if (!isMigrationMasterDeployed) await deployMigrationMaster(); From b58bdf1eb3a3156a0e389e811b001367c9c10fd5 Mon Sep 17 00:00:00 2001 From: Gusarich Date: Sun, 21 May 2023 18:57:28 +0300 Subject: [PATCH 11/30] real check for `isNewMinterDeployed` --- src/store/jetton-store/useJettonStore.ts | 49 +++++++++++++++++------- 1 file changed, 35 insertions(+), 14 deletions(-) diff --git a/src/store/jetton-store/useJettonStore.ts b/src/store/jetton-store/useJettonStore.ts index 3a7dd84..946305f 100644 --- a/src/store/jetton-store/useJettonStore.ts +++ b/src/store/jetton-store/useJettonStore.ts @@ -1,6 +1,6 @@ import { TonConnection, ChromeExtensionWalletProvider } from "@ton-defi.org/ton-connection"; -import { jettonDeployController } from "lib/deploy-controller"; -import { zeroAddress } from "lib/utils"; +import { JettonDeployParams, jettonDeployController } from "lib/deploy-controller"; +import { createDeployParams, zeroAddress } from "lib/utils"; import { useRecoilState, useResetRecoilState } from "recoil"; import WalletConnection from "services/wallet-connection"; import { Address, Cell } from "ton"; @@ -12,6 +12,8 @@ import useConnectionStore from "store/connection-store/useConnectionStore"; import { getUrlParam, isValidAddress } from "utils"; import { useJettonAddress } from "hooks/useJettonAddress"; import { JETTON_MINTER_CODE } from "lib/jetton-minter"; +import { BN } from "bn.js"; +import { ContractDeployer } from "lib/contract-deployer"; function useJettonStore() { const [state, setState] = useRecoilState(jettonStateAtom); @@ -143,23 +145,25 @@ function useJettonStore() { await jettonDeployController.getJettonMinterCode(parsedJettonMaster), )[0]; - const isNewMinterDeployed = false; // TODO - const isMigrationMasterDeployed = false; // TODO - const mintedJettonsToMaster = false; // TODO + const name = result.minter.metadata.name; + const symbol = result.minter.metadata.symbol; + const jettonImage = image ?? QuestiomMarkImg; + const description = result.minter.metadata.description; + const decimals = result.minter.metadata.decimals || "9"; setState((prevState) => { return { ...prevState, isJettonDeployerFaultyOnChainData: result.minter.isJettonDeployerFaultyOnChainData, persistenceType: result.minter.persistenceType, - description: result.minter.metadata.description, - jettonImage: image ?? QuestiomMarkImg, + description, + jettonImage, totalSupply: result.minter.totalSupply, - name: result.minter.metadata.name, - symbol: result.minter.metadata.symbol, + name, + symbol, adminRevokedOwnership: _adminAddress === zeroAddress().toFriendly(), isAdmin: admin, - decimals: result.minter.metadata.decimals || "9", + decimals, adminAddress: _adminAddress, balance: result.jettonWallet ? result.jettonWallet.balance : undefined, jettonWalletAddress: result.jettonWallet?.jWalletAddress.toFriendly(), @@ -167,12 +171,29 @@ function useJettonStore() { isMyWallet, selectedWalletAddress: address, isCodeOld: !minterCode.equals(JETTON_MINTER_CODE), - isNewMinterDeployed, - isMigrationMasterDeployed, - mintedJettonsToMaster, - migrationStarted: false, }; }); + + if (address) { + const params: JettonDeployParams = { + owner: Address.parse(address), + onchainMetaData: { + name: name!, + symbol: symbol!, + image: jettonImage, + description: description, + decimals: parseInt(decimals!).toFixed(0), + }, + amountToMint: new BN(0), + }; + const deployParams = createDeployParams(params); + const contractAddress = new ContractDeployer().addressForContract(deployParams); + const isNewMinterDeployed = WalletConnection.isContractDeployed(contractAddress); + setState((prevState) => ({ + ...prevState, + isNewMinterDeployed, + })); + } } catch (error) { if (error instanceof Error) { showNotification( From 437c4e06ad22d79a645bb8b7cc75543265a7fc89 Mon Sep 17 00:00:00 2001 From: Gusarich Date: Wed, 24 May 2023 07:49:24 +0300 Subject: [PATCH 12/30] show migration button only if connected wallet and if migration didn't happen yet --- src/pages/jetton/dataRow/token/Token.tsx | 47 ++++++++++++++---------- 1 file changed, 27 insertions(+), 20 deletions(-) diff --git a/src/pages/jetton/dataRow/token/Token.tsx b/src/pages/jetton/dataRow/token/Token.tsx index 1500507..46a1ee0 100644 --- a/src/pages/jetton/dataRow/token/Token.tsx +++ b/src/pages/jetton/dataRow/token/Token.tsx @@ -47,6 +47,10 @@ export const Token = () => { decimals, isImageBroken, isCodeOld, + selectedWalletAddress, + isNewMinterDeployed, + isMigrationMasterDeployed, + mintedJettonsToMaster, } = useJettonStore(); const [openEdit, setOpenEdit] = useState(false); const [openMigrationPopup, setOpenMigrationPopup] = useState(false); @@ -108,26 +112,29 @@ export const Token = () => { )} { - /* isAdmin && */ isCodeOld && !jettonLoading && ( - - setOpenMigrationPopup(true)}> - - Pen Icon - Migration - - - - ) + /* isAdmin && */ isCodeOld && + !jettonLoading && + selectedWalletAddress && + !(isNewMinterDeployed && isMigrationMasterDeployed && mintedJettonsToMaster) && ( + + setOpenMigrationPopup(true)}> + + Pen Icon + Migration + + + + ) } {!isAdmin && isJettonDeployerFaultyOnChainData && ( From 12e1ea9e3dd76f48415365d737e603f90cefb83a Mon Sep 17 00:00:00 2001 From: Gusarich Date: Wed, 24 May 2023 08:11:16 +0300 Subject: [PATCH 13/30] add a button that will redirect user to a new version of the minter --- src/pages/jetton/dataRow/token/Token.tsx | 23 +++++++++++++++++++++++ src/store/jetton-store/index.ts | 2 ++ 2 files changed, 25 insertions(+) diff --git a/src/pages/jetton/dataRow/token/Token.tsx b/src/pages/jetton/dataRow/token/Token.tsx index 46a1ee0..1570a21 100644 --- a/src/pages/jetton/dataRow/token/Token.tsx +++ b/src/pages/jetton/dataRow/token/Token.tsx @@ -28,6 +28,7 @@ import { AppButton } from "components/appButton"; import pen from "assets/icons/pen.svg"; import { CenteringWrapper } from "components/footer/styled"; import { MigrationPopup } from "pages/jetton/migration"; +import { useNavigate } from "react-router-dom"; export const Token = () => { const { @@ -51,9 +52,11 @@ export const Token = () => { isNewMinterDeployed, isMigrationMasterDeployed, mintedJettonsToMaster, + newMinterAddress, } = useJettonStore(); const [openEdit, setOpenEdit] = useState(false); const [openMigrationPopup, setOpenMigrationPopup] = useState(false); + const navigate = useNavigate(); return ( @@ -136,6 +139,26 @@ export const Token = () => {
) } + {isNewMinterDeployed && isMigrationMasterDeployed && mintedJettonsToMaster && ( + + navigate(`/jetton/${newMinterAddress}`)}> + + New Button Icon + New version + + + + )} {!isAdmin && isJettonDeployerFaultyOnChainData && ( diff --git a/src/store/jetton-store/index.ts b/src/store/jetton-store/index.ts index f8908c0..8c95014 100644 --- a/src/store/jetton-store/index.ts +++ b/src/store/jetton-store/index.ts @@ -26,6 +26,7 @@ export interface JettonStoreState { isMigrationMasterDeployed: boolean; mintedJettonsToMaster: boolean; migrationStarted: boolean; + newMinterAddress: string; } const jettonStateAtom = atom({ @@ -54,6 +55,7 @@ const jettonStateAtom = atom({ isMigrationMasterDeployed: false, mintedJettonsToMaster: false, migrationStarted: false, + newMinterAddress: "", }, }); From d9526dc603db598f10c07a04811751f471c7f2ba Mon Sep 17 00:00:00 2001 From: Gusarich Date: Tue, 6 Jun 2023 17:31:55 +0300 Subject: [PATCH 14/30] fix redirects --- src/pages/jetton/migration.tsx | 8 ++------ src/store/jetton-store/useJettonStore.ts | 5 +++-- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/pages/jetton/migration.tsx b/src/pages/jetton/migration.tsx index 5943d9d..3a09b1f 100644 --- a/src/pages/jetton/migration.tsx +++ b/src/pages/jetton/migration.tsx @@ -24,6 +24,7 @@ export function MigrationPopup({ isMigrationMasterDeployed, mintedJettonsToMaster, migrationStarted, + newMinterAddress, setNewMinterDeployed, setMigrationMasterDeployed, setMintedJettonsToMaster, @@ -109,11 +110,6 @@ export function MigrationPopup({ ); }; - const redirectToNewPage = () => { - const newJettonAddress = "EQAGPPuLtcu8BimtY8TFVrpJ-E36akEFZHexCSD_BNQl_QrW"; - navigate(`/jetton/${newJettonAddress}`); - }; - return ( {!migrationStarted ? ( @@ -184,7 +180,7 @@ export function MigrationPopup({ width={200} onClick={() => { onClose(); - redirectToNewPage(); + navigate(`/jetton/${newMinterAddress}`); }}> Go to the new Jetton
diff --git a/src/store/jetton-store/useJettonStore.ts b/src/store/jetton-store/useJettonStore.ts index 946305f..3a7e9d9 100644 --- a/src/store/jetton-store/useJettonStore.ts +++ b/src/store/jetton-store/useJettonStore.ts @@ -187,11 +187,12 @@ function useJettonStore() { amountToMint: new BN(0), }; const deployParams = createDeployParams(params); - const contractAddress = new ContractDeployer().addressForContract(deployParams); - const isNewMinterDeployed = WalletConnection.isContractDeployed(contractAddress); + const newMinterAddress = new ContractDeployer().addressForContract(deployParams); + const isNewMinterDeployed = WalletConnection.isContractDeployed(newMinterAddress); setState((prevState) => ({ ...prevState, isNewMinterDeployed, + newMinterAddress: newMinterAddress.toString(), })); } } catch (error) { From 2c107dc3dc23d18f52bed23268ea067f730e7bc1 Mon Sep 17 00:00:00 2001 From: Gusarich Date: Thu, 29 Jun 2023 07:34:40 +0300 Subject: [PATCH 15/30] add migration master and helper contracts --- .../contracts/MigrationHelper.compiled.json | 3 + .../contracts/MigrationMaster.compiled.json | 3 + src/lib/migrations.ts | 57 +++++++++++++++++++ 3 files changed, 63 insertions(+) create mode 100644 src/lib/contracts/MigrationHelper.compiled.json create mode 100644 src/lib/contracts/MigrationMaster.compiled.json create mode 100644 src/lib/migrations.ts diff --git a/src/lib/contracts/MigrationHelper.compiled.json b/src/lib/contracts/MigrationHelper.compiled.json new file mode 100644 index 0000000..34c22bb --- /dev/null +++ b/src/lib/contracts/MigrationHelper.compiled.json @@ -0,0 +1,3 @@ +{ + "hex": "b5ee9c7241020701000122000114ff00f4a413f4bcf2c80b010202d00302008969c08208403e29fa97232c7c4f2cfd400fe80be10b3c5be10f3c5b2c0208402faf0803e80b2c03e10f3c5b25c60063232c17e1073c5a08403b9aca03e80b2dab3325c7ec0203f7d76d176fd906ba4e000492f827001410808f0d1805cf968fcf6a2687d207d2000fc317d2000fc31ea187c142cb82a1009aa0a01e428027d012c678b00e78b666491646580897a007a00658064fc80383a6465816503e5ffe4e87c30e86981fd201800b8d8492f81f000e98f90c1083cf23a475d7187e99ffd001800c060504003af006708018c8cb05f843cf1602821011e1a300a112fa02cb6ac970fb0000320182107362d09cba945f03db31e1f84112c705b3935bdb31e0001831f84312c705b3935bdb31e0512f215e" +} diff --git a/src/lib/contracts/MigrationMaster.compiled.json b/src/lib/contracts/MigrationMaster.compiled.json new file mode 100644 index 0000000..70479bc --- /dev/null +++ b/src/lib/contracts/MigrationMaster.compiled.json @@ -0,0 +1,3 @@ +{ + "hex": "b5ee9c7241020a010001df000114ff00f4a413f4bcf2c80b01020162030200eba0df8dda89a1f481f481a9a861f050a084e0a84026a8280790a009f404b19e2c039e2d99924591960225e801e801960193f200e0e9919605940f97ff93a1f0c3f05004e0a84026a8280790a009f404b19e2c039e2d99924591960225e801e801960193f200e0e9919605940f97ff93a1f0c5f083f0850202cc0504005fdb841082caf83de64658f89659fac7d017c14678b658064b8c00c646582fc20e78b41057d78407d0165b56664b8fd8040201200706007bf3810410807c53f52e4658f8a659fa8027d0110e78b00e78b658041057d78407d01658064b8c00c646582fc21678b410802faf0807d0165b56664b8fd8040129d106ba4e000492f827001410805f5e1005cf968fcc0801fced44d0fa40fa40d4d430f828504270542013541403c85004fa0258cf1601cf16ccc922c8cb0112f400f400cb00c9f9007074c8cb02ca07cbffc9d0f861f8280270542013541403c85004fa0258cf1601cf16ccc922c8cb0112f400f400cb00c9f9007074c8cb02ca07cbffc9d0f862d0d303fa403002d31f0271b0f8411409007cc705b313b10282107362d09cbd12b1915be0d33ffa00fa403171d721547120f00702f008708018c8cb0558cf160282100bebc200a112fa02cb6ac970fb0041907573" +} diff --git a/src/lib/migrations.ts b/src/lib/migrations.ts new file mode 100644 index 0000000..0fde97a --- /dev/null +++ b/src/lib/migrations.ts @@ -0,0 +1,57 @@ +import BN from "bn.js"; +import { Cell, beginCell, Address, beginDict, Slice, toNano } from "ton"; + +import masterHex from "./contracts/MigrationMaster.compiled.json"; +import helperHex from "./contracts/MigrationHelper.compiled.json"; +// @ts-ignore +import { Sha256 } from "@aws-crypto/sha256-js"; +import axios from "axios"; +import { getClient } from "./get-ton-client"; + +export const MIGRATION_MASTER_CODE = Cell.fromBoc(masterHex.hex)[0]; +export const MIGRATION_HELPER_CODE = Cell.fromBoc(helperHex.hex)[0]; // code cell from build output + +enum OPS { + Migrate = 0x79e4748e, +} + +export type MigrationMasterConfig = { + oldJettonMinter: Address; + newJettonMinter: Address; + oldWalletCode?: Cell; + newWalletCode?: Cell; +}; + +export async function migrationMasterConfigToCell(config: MigrationMasterConfig): Promise { + const client = await getClient(); + const oldWalletCode = (await client.callGetMethod(config.oldJettonMinter, "get_jetton_data")) + .stack[4]; + const newWalletCode = (await client.callGetMethod(config.newJettonMinter, "get_jetton_data")) + .stack[4]; + + return beginCell() + .storeAddress(config.oldJettonMinter) + .storeAddress(config.newJettonMinter) + .storeRef(config.oldWalletCode || oldWalletCode) + .storeRef(config.newWalletCode || newWalletCode) + .endCell(); +} + +export type MigrationHelperConfig = { + oldJettonMinter: Address; + migrationMaster: Address; + recipient: Address; + oldWalletCode?: Cell; +}; + +export async function migrationHelperConfigToCell(config: MigrationHelperConfig): Promise { + const client = await getClient(); + const oldWalletCode = (await client.callGetMethod(config.oldJettonMinter, "get_jetton_data")) + .stack[4]; + return beginCell() + .storeAddress(config.oldJettonMinter) + .storeAddress(config.migrationMaster) + .storeAddress(config.recipient) + .storeRef(config.oldWalletCode || oldWalletCode) + .endCell(); +} From b9f898606cd5633daf9965e1dddfedbef5ed44d1 Mon Sep 17 00:00:00 2001 From: Gusarich Date: Thu, 29 Jun 2023 07:38:29 +0300 Subject: [PATCH 16/30] add `migrateBody` --- src/lib/migrations.ts | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/lib/migrations.ts b/src/lib/migrations.ts index 0fde97a..561584b 100644 --- a/src/lib/migrations.ts +++ b/src/lib/migrations.ts @@ -1,12 +1,9 @@ -import BN from "bn.js"; -import { Cell, beginCell, Address, beginDict, Slice, toNano } from "ton"; +import { Cell, beginCell, Address } from "ton"; import masterHex from "./contracts/MigrationMaster.compiled.json"; import helperHex from "./contracts/MigrationHelper.compiled.json"; -// @ts-ignore -import { Sha256 } from "@aws-crypto/sha256-js"; -import axios from "axios"; import { getClient } from "./get-ton-client"; +import BN from "bn.js"; export const MIGRATION_MASTER_CODE = Cell.fromBoc(masterHex.hex)[0]; export const MIGRATION_HELPER_CODE = Cell.fromBoc(helperHex.hex)[0]; // code cell from build output @@ -55,3 +52,7 @@ export async function migrationHelperConfigToCell(config: MigrationHelperConfig) .storeRef(config.oldWalletCode || oldWalletCode) .endCell(); } + +export function migrateBody(amount: BN): Cell { + return beginCell().storeUint(OPS.Migrate, 32).storeUint(1, 64).storeCoins(amount).endCell(); +} From 9d0eb0521661946bd4e28a6fa2e948e706c347a1 Mon Sep 17 00:00:00 2001 From: Gusarich Date: Thu, 29 Jun 2023 07:48:36 +0300 Subject: [PATCH 17/30] real check for 2nd transaction --- src/store/jetton-store/useJettonStore.ts | 26 +++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/src/store/jetton-store/useJettonStore.ts b/src/store/jetton-store/useJettonStore.ts index 3a7e9d9..9f2eecb 100644 --- a/src/store/jetton-store/useJettonStore.ts +++ b/src/store/jetton-store/useJettonStore.ts @@ -14,6 +14,11 @@ import { useJettonAddress } from "hooks/useJettonAddress"; import { JETTON_MINTER_CODE } from "lib/jetton-minter"; import { BN } from "bn.js"; import { ContractDeployer } from "lib/contract-deployer"; +import { + MIGRATION_MASTER_CODE, + MigrationMasterConfig, + migrationMasterConfigToCell, +} from "lib/migrations"; function useJettonStore() { const [state, setState] = useRecoilState(jettonStateAtom); @@ -175,7 +180,7 @@ function useJettonStore() { }); if (address) { - const params: JettonDeployParams = { + const minterParams: JettonDeployParams = { owner: Address.parse(address), onchainMetaData: { name: name!, @@ -186,13 +191,28 @@ function useJettonStore() { }, amountToMint: new BN(0), }; - const deployParams = createDeployParams(params); - const newMinterAddress = new ContractDeployer().addressForContract(deployParams); + const minterDeployParams = createDeployParams(minterParams); + const newMinterAddress = new ContractDeployer().addressForContract(minterDeployParams); const isNewMinterDeployed = WalletConnection.isContractDeployed(newMinterAddress); + + const migrationMasterConfig: MigrationMasterConfig = { + oldJettonMinter: parsedJettonMaster, + newJettonMinter: newMinterAddress, + }; + const migrationMasterAddress = new ContractDeployer().addressForContract({ + code: MIGRATION_MASTER_CODE, + data: await migrationMasterConfigToCell(migrationMasterConfig), + deployer: newMinterAddress, //anything + value: new BN(0), //anything + }); + const isMigrationMasterDeployed = + WalletConnection.isContractDeployed(migrationMasterAddress); + setState((prevState) => ({ ...prevState, isNewMinterDeployed, newMinterAddress: newMinterAddress.toString(), + isMigrationMasterDeployed, })); } } catch (error) { From e14375d2cca34625ae0ff376b1c651960677eee3 Mon Sep 17 00:00:00 2001 From: Gusarich Date: Thu, 29 Jun 2023 07:55:57 +0300 Subject: [PATCH 18/30] actual check for 3rd transaction --- src/store/jetton-store/useJettonStore.ts | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/store/jetton-store/useJettonStore.ts b/src/store/jetton-store/useJettonStore.ts index 9f2eecb..2f9aea5 100644 --- a/src/store/jetton-store/useJettonStore.ts +++ b/src/store/jetton-store/useJettonStore.ts @@ -19,6 +19,7 @@ import { MigrationMasterConfig, migrationMasterConfigToCell, } from "lib/migrations"; +import { getClient } from "lib/get-ton-client"; function useJettonStore() { const [state, setState] = useRecoilState(jettonStateAtom); @@ -202,17 +203,38 @@ function useJettonStore() { const migrationMasterAddress = new ContractDeployer().addressForContract({ code: MIGRATION_MASTER_CODE, data: await migrationMasterConfigToCell(migrationMasterConfig), - deployer: newMinterAddress, //anything + deployer: Address.parse(address), //anything value: new BN(0), //anything }); const isMigrationMasterDeployed = WalletConnection.isContractDeployed(migrationMasterAddress); + let mintedJettonsToMaster = false; + + if (isNewMinterDeployed && isMigrationMasterDeployed) { + const result = await jettonDeployController.getJettonDetails( + newMinterAddress, + Address.parse(address), + connection, + ); + + if (!result) { + console.log("empty"); + return; + } + + const migrationMasterJettonBalance = result.jettonWallet?.balance; + + if (migrationMasterJettonBalance?.gt(new BN(0))) { + mintedJettonsToMaster = true; + } + } setState((prevState) => ({ ...prevState, isNewMinterDeployed, newMinterAddress: newMinterAddress.toString(), isMigrationMasterDeployed, + mintedJettonsToMaster, })); } } catch (error) { From 02b7f18e488f88d2c137439e4ee2cd336769e740 Mon Sep 17 00:00:00 2001 From: Gusarich Date: Thu, 29 Jun 2023 19:47:34 +0300 Subject: [PATCH 19/30] send an actual first transaction --- src/pages/jetton/migration.tsx | 65 +++++++++++++++++++++++++++++----- 1 file changed, 56 insertions(+), 9 deletions(-) diff --git a/src/pages/jetton/migration.tsx b/src/pages/jetton/migration.tsx index 3a09b1f..10743d5 100644 --- a/src/pages/jetton/migration.tsx +++ b/src/pages/jetton/migration.tsx @@ -10,6 +10,15 @@ import CheckCircleIcon from "@mui/icons-material/CheckCircle"; import { useNavigate } from "react-router-dom"; import WalletConnection from "services/wallet-connection"; import useConnectionStore from "store/connection-store/useConnectionStore"; +import { TonConnection } from "@ton-defi.org/ton-connection"; +import { Address, Cell } from "ton"; +import { JettonDeployParams, jettonDeployController } from "lib/deploy-controller"; +import { createDeployParams } from "lib/utils"; +import BN from "bn.js"; +import { ContractDeployer } from "lib/contract-deployer"; +import { toDecimalsBN } from "utils"; +import analytics from "services/analytics"; +import useNotification from "hooks/useNotification"; export function MigrationPopup({ open, @@ -25,12 +34,18 @@ export function MigrationPopup({ mintedJettonsToMaster, migrationStarted, newMinterAddress, + decimals, + name, + jettonImage, + description, + totalSupply, setNewMinterDeployed, setMigrationMasterDeployed, setMintedJettonsToMaster, setMigrationStarted, } = useJettonStore(); const { address } = useConnectionStore(); + const { showNotification } = useNotification(); const navigate = useNavigate(); @@ -44,24 +59,56 @@ export function MigrationPopup({ throw new Error("Wallet not connected"); } setMigrationStarted(true); - if (!isNewMinterDeployed) await deployNewJetton(); - if (!isMigrationMasterDeployed) await deployMigrationMaster(); - if (!mintedJettonsToMaster) await mintJettonsToMaster(); + if (!isNewMinterDeployed) await deployNewJetton(connection); + if (!isMigrationMasterDeployed) await deployMigrationMaster(connection); + if (!mintedJettonsToMaster) await mintJettonsToMaster(connection); }; - const deployNewJetton = async () => { - // TODO - await new Promise((r) => setTimeout(r, 1000)); - setNewMinterDeployed(true); + const deployNewJetton = async (connection: TonConnection) => { + if (!address || !connection) { + throw new Error("Wallet not connected"); + } + + const params: JettonDeployParams = { + owner: Address.parse(address), + onchainMetaData: { + name: name!, + symbol: symbol!, + image: jettonImage, + description: description, + decimals: parseInt(decimals!).toFixed(0), + }, + amountToMint: totalSupply!, + }; + + const deployParams = createDeployParams(params); + const contractAddress = new ContractDeployer().addressForContract(deployParams); + + const isDeployed = await WalletConnection.isContractDeployed(contractAddress); + + if (isDeployed) { + setNewMinterDeployed(true); + return; + } + + try { + const result = await jettonDeployController.createJetton(params, connection); + } catch (err) { + if (err instanceof Error) { + showNotification(<>{err.message}, "error"); + } + } finally { + setNewMinterDeployed(true); + } }; - const deployMigrationMaster = async () => { + const deployMigrationMaster = async (connection: TonConnection) => { // TODO await new Promise((r) => setTimeout(r, 1000)); setMigrationMasterDeployed(true); }; - const mintJettonsToMaster = async () => { + const mintJettonsToMaster = async (connection: TonConnection) => { // TODO await new Promise((r) => setTimeout(r, 1000)); setMintedJettonsToMaster(true); From c59ae0d4b27c03fbb33b619b02ad97068311fe1a Mon Sep 17 00:00:00 2001 From: Gusarich Date: Thu, 29 Jun 2023 19:57:17 +0300 Subject: [PATCH 20/30] fix --- src/store/jetton-store/useJettonStore.ts | 60 ++++++++++++------------ 1 file changed, 31 insertions(+), 29 deletions(-) diff --git a/src/store/jetton-store/useJettonStore.ts b/src/store/jetton-store/useJettonStore.ts index 2f9aea5..19d2027 100644 --- a/src/store/jetton-store/useJettonStore.ts +++ b/src/store/jetton-store/useJettonStore.ts @@ -195,37 +195,39 @@ function useJettonStore() { const minterDeployParams = createDeployParams(minterParams); const newMinterAddress = new ContractDeployer().addressForContract(minterDeployParams); const isNewMinterDeployed = WalletConnection.isContractDeployed(newMinterAddress); - - const migrationMasterConfig: MigrationMasterConfig = { - oldJettonMinter: parsedJettonMaster, - newJettonMinter: newMinterAddress, - }; - const migrationMasterAddress = new ContractDeployer().addressForContract({ - code: MIGRATION_MASTER_CODE, - data: await migrationMasterConfigToCell(migrationMasterConfig), - deployer: Address.parse(address), //anything - value: new BN(0), //anything - }); - const isMigrationMasterDeployed = - WalletConnection.isContractDeployed(migrationMasterAddress); + let isMigrationMasterDeployed = false; let mintedJettonsToMaster = false; - if (isNewMinterDeployed && isMigrationMasterDeployed) { - const result = await jettonDeployController.getJettonDetails( - newMinterAddress, - Address.parse(address), - connection, - ); - - if (!result) { - console.log("empty"); - return; - } - - const migrationMasterJettonBalance = result.jettonWallet?.balance; - - if (migrationMasterJettonBalance?.gt(new BN(0))) { - mintedJettonsToMaster = true; + if (isNewMinterDeployed) { + const migrationMasterConfig: MigrationMasterConfig = { + oldJettonMinter: parsedJettonMaster, + newJettonMinter: newMinterAddress, + }; + const migrationMasterAddress = new ContractDeployer().addressForContract({ + code: MIGRATION_MASTER_CODE, + data: await migrationMasterConfigToCell(migrationMasterConfig), + deployer: Address.parse(address), //anything + value: new BN(0), //anything + }); + isMigrationMasterDeployed = WalletConnection.isContractDeployed(migrationMasterAddress); + + if (isMigrationMasterDeployed) { + const result = await jettonDeployController.getJettonDetails( + newMinterAddress, + Address.parse(address), + connection, + ); + + if (!result) { + console.log("empty"); + return; + } + + const migrationMasterJettonBalance = result.jettonWallet?.balance; + + if (migrationMasterJettonBalance?.gt(new BN(0))) { + mintedJettonsToMaster = true; + } } } From 7e741e6f709e2c739a60ce76bbd7af148e10e7ea Mon Sep 17 00:00:00 2001 From: Gusarich Date: Thu, 29 Jun 2023 20:31:07 +0300 Subject: [PATCH 21/30] send an actual second transaction --- src/lib/contract-deployer.ts | 1 + src/lib/migrations.ts | 56 +++++++++++++++++++++++++++++++--- src/pages/jetton/migration.tsx | 50 ++++++++++++++++++++++++++++-- 3 files changed, 99 insertions(+), 8 deletions(-) diff --git a/src/lib/contract-deployer.ts b/src/lib/contract-deployer.ts index 12ca2f9..34d1a9a 100644 --- a/src/lib/contract-deployer.ts +++ b/src/lib/contract-deployer.ts @@ -13,6 +13,7 @@ interface ContractDeployDetails { export class ContractDeployer { addressForContract(params: ContractDeployDetails) { + console.log(params.data, params.code); return contractAddress({ workchain: 0, initialData: params.data, diff --git a/src/lib/migrations.ts b/src/lib/migrations.ts index 561584b..b9984d5 100644 --- a/src/lib/migrations.ts +++ b/src/lib/migrations.ts @@ -1,9 +1,13 @@ -import { Cell, beginCell, Address } from "ton"; +import { Cell, beginCell, Address, TonClient } from "ton"; import masterHex from "./contracts/MigrationMaster.compiled.json"; import helperHex from "./contracts/MigrationHelper.compiled.json"; import { getClient } from "./get-ton-client"; import BN from "bn.js"; +import { TonConnection } from "@ton-defi.org/ton-connection"; +import { ContractDeployer } from "./contract-deployer"; +import WalletConnection from "services/wallet-connection"; +import { waitForContractDeploy } from "./utils"; export const MIGRATION_MASTER_CODE = Cell.fromBoc(masterHex.hex)[0]; export const MIGRATION_HELPER_CODE = Cell.fromBoc(helperHex.hex)[0]; // code cell from build output @@ -12,6 +16,8 @@ enum OPS { Migrate = 0x79e4748e, } +export const MIGRATION_MASTER_DEPLOY_GAS = new BN("100000000"); + export type MigrationMasterConfig = { oldJettonMinter: Address; newJettonMinter: Address; @@ -21,10 +27,18 @@ export type MigrationMasterConfig = { export async function migrationMasterConfigToCell(config: MigrationMasterConfig): Promise { const client = await getClient(); - const oldWalletCode = (await client.callGetMethod(config.oldJettonMinter, "get_jetton_data")) - .stack[4]; - const newWalletCode = (await client.callGetMethod(config.newJettonMinter, "get_jetton_data")) - .stack[4]; + const oldWalletCode = Cell.fromBoc( + Buffer.from( + (await client.callGetMethod(config.oldJettonMinter, "get_jetton_data")).stack[4][1].bytes, + "base64", + ).toString("hex"), + )[0]; + const newWalletCode = Cell.fromBoc( + Buffer.from( + (await client.callGetMethod(config.newJettonMinter, "get_jetton_data")).stack[4][1].bytes, + "base64", + ).toString("hex"), + )[0]; return beginCell() .storeAddress(config.oldJettonMinter) @@ -56,3 +70,35 @@ export async function migrationHelperConfigToCell(config: MigrationHelperConfig) export function migrateBody(amount: BN): Cell { return beginCell().storeUint(OPS.Migrate, 32).storeUint(1, 64).storeCoins(amount).endCell(); } + +export async function createMigrationMaster( + config: MigrationMasterConfig, + tonConnection: TonConnection, + owner: Address, +): Promise
{ + const contractDeployer = new ContractDeployer(); + const tc = await getClient(); + + // params.onProgress?.(JettonDeployState.BALANCE_CHECK); + const balance = await tc.getBalance(owner); + if (balance.lt(MIGRATION_MASTER_DEPLOY_GAS)) + throw new Error("Not enough balance in deployer wallet"); + const params = { + code: MIGRATION_MASTER_CODE, + data: await migrationMasterConfigToCell(config), + deployer: owner, //anything + value: MIGRATION_MASTER_DEPLOY_GAS, + }; + const migrationMasterAddress = new ContractDeployer().addressForContract(params); + const isDeployed = WalletConnection.isContractDeployed(migrationMasterAddress); + + if (await tc.isContractDeployed(migrationMasterAddress)) { + // params.onProgress?.(JettonDeployState.ALREADY_DEPLOYED); + } else { + await contractDeployer.deployContract(params, tonConnection); + // params.onProgress?.(JettonDeployState.AWAITING_MINTER_DEPLOY); + await waitForContractDeploy(migrationMasterAddress, tc); + } + + return migrationMasterAddress; +} diff --git a/src/pages/jetton/migration.tsx b/src/pages/jetton/migration.tsx index 10743d5..410f4b3 100644 --- a/src/pages/jetton/migration.tsx +++ b/src/pages/jetton/migration.tsx @@ -19,6 +19,14 @@ import { ContractDeployer } from "lib/contract-deployer"; import { toDecimalsBN } from "utils"; import analytics from "services/analytics"; import useNotification from "hooks/useNotification"; +import { + MIGRATION_MASTER_CODE, + MIGRATION_MASTER_DEPLOY_GAS, + MigrationMasterConfig, + createMigrationMaster, + migrationMasterConfigToCell, +} from "lib/migrations"; +import { useJettonAddress } from "hooks/useJettonAddress"; export function MigrationPopup({ open, @@ -46,6 +54,7 @@ export function MigrationPopup({ } = useJettonStore(); const { address } = useConnectionStore(); const { showNotification } = useNotification(); + const { jettonAddress } = useJettonAddress(); const navigate = useNavigate(); @@ -103,9 +112,44 @@ export function MigrationPopup({ }; const deployMigrationMaster = async (connection: TonConnection) => { - // TODO - await new Promise((r) => setTimeout(r, 1000)); - setMigrationMasterDeployed(true); + if (!address || !connection) { + throw new Error("Wallet not connected"); + } + + const parsedJettonMaster = Address.parse(jettonAddress!); + + const migrationMasterConfig: MigrationMasterConfig = { + oldJettonMinter: parsedJettonMaster, + newJettonMinter: Address.parse(newMinterAddress), + }; + const params = { + code: MIGRATION_MASTER_CODE, + data: await migrationMasterConfigToCell(migrationMasterConfig), + deployer: Address.parse(address), + value: MIGRATION_MASTER_DEPLOY_GAS, + }; + console.log(params); + const migrationMasterAddress = new ContractDeployer().addressForContract(params); + const isDeployed = WalletConnection.isContractDeployed(migrationMasterAddress); + + if (isDeployed) { + setMigrationMasterDeployed(true); + return; + } + + try { + const result = await createMigrationMaster( + migrationMasterConfig, + connection, + Address.parse(address), + ); + } catch (err) { + if (err instanceof Error) { + showNotification(<>{err.message}, "error"); + } + } finally { + setMigrationMasterDeployed(true); + } }; const mintJettonsToMaster = async (connection: TonConnection) => { From 28895fa3f2c2bedf4324cb2fb92cd4d8291c0713 Mon Sep 17 00:00:00 2001 From: Gusarich Date: Thu, 29 Jun 2023 20:48:31 +0300 Subject: [PATCH 22/30] send an actual third transaction + fixes --- src/lib/migrations.ts | 2 +- src/pages/deployer/index.tsx | 4 +- src/pages/jetton/migration.tsx | 54 +++++++++++++++++++++--- src/store/jetton-store/useJettonStore.ts | 16 +++++-- 4 files changed, 64 insertions(+), 12 deletions(-) diff --git a/src/lib/migrations.ts b/src/lib/migrations.ts index b9984d5..217a89d 100644 --- a/src/lib/migrations.ts +++ b/src/lib/migrations.ts @@ -90,7 +90,7 @@ export async function createMigrationMaster( value: MIGRATION_MASTER_DEPLOY_GAS, }; const migrationMasterAddress = new ContractDeployer().addressForContract(params); - const isDeployed = WalletConnection.isContractDeployed(migrationMasterAddress); + const isDeployed = tc.isContractDeployed(migrationMasterAddress); if (await tc.isContractDeployed(migrationMasterAddress)) { // params.onProgress?.(JettonDeployState.ALREADY_DEPLOYED); diff --git a/src/pages/deployer/index.tsx b/src/pages/deployer/index.tsx index 2e2af9d..59571e4 100644 --- a/src/pages/deployer/index.tsx +++ b/src/pages/deployer/index.tsx @@ -24,6 +24,7 @@ import { offchainFormSpec, onchainFormSpec } from "./data"; import { Form } from "components/form"; import { GithubButton } from "pages/deployer/githubButton"; import { useNavigatePreserveQuery } from "lib/hooks/useNavigatePreserveQuery"; +import { getClient } from "lib/get-ton-client"; const DEFAULT_DECIMALS = 9; @@ -74,7 +75,8 @@ function DeployerPage() { const deployParams = createDeployParams(params, data.offchainUri); const contractAddress = new ContractDeployer().addressForContract(deployParams); - const isDeployed = await WalletConnection.isContractDeployed(contractAddress); + const client = await getClient(); + const isDeployed = await client.isContractDeployed(contractAddress); if (isDeployed) { showNotification( diff --git a/src/pages/jetton/migration.tsx b/src/pages/jetton/migration.tsx index 410f4b3..84c2f8e 100644 --- a/src/pages/jetton/migration.tsx +++ b/src/pages/jetton/migration.tsx @@ -11,7 +11,7 @@ import { useNavigate } from "react-router-dom"; import WalletConnection from "services/wallet-connection"; import useConnectionStore from "store/connection-store/useConnectionStore"; import { TonConnection } from "@ton-defi.org/ton-connection"; -import { Address, Cell } from "ton"; +import { Address, Cell, beginCell } from "ton"; import { JettonDeployParams, jettonDeployController } from "lib/deploy-controller"; import { createDeployParams } from "lib/utils"; import BN from "bn.js"; @@ -27,6 +27,9 @@ import { migrationMasterConfigToCell, } from "lib/migrations"; import { useJettonAddress } from "hooks/useJettonAddress"; +import { transfer } from "lib/jetton-minter"; +import { cellToAddress, makeGetCall } from "lib/make-get-call"; +import { getClient } from "lib/get-ton-client"; export function MigrationPopup({ open, @@ -47,6 +50,7 @@ export function MigrationPopup({ jettonImage, description, totalSupply, + jettonWalletAddress, setNewMinterDeployed, setMigrationMasterDeployed, setMintedJettonsToMaster, @@ -93,7 +97,8 @@ export function MigrationPopup({ const deployParams = createDeployParams(params); const contractAddress = new ContractDeployer().addressForContract(deployParams); - const isDeployed = await WalletConnection.isContractDeployed(contractAddress); + const client = await getClient(); + const isDeployed = await client.isContractDeployed(contractAddress); if (isDeployed) { setNewMinterDeployed(true); @@ -128,9 +133,9 @@ export function MigrationPopup({ deployer: Address.parse(address), value: MIGRATION_MASTER_DEPLOY_GAS, }; - console.log(params); const migrationMasterAddress = new ContractDeployer().addressForContract(params); - const isDeployed = WalletConnection.isContractDeployed(migrationMasterAddress); + const client = await getClient(); + const isDeployed = await client.isContractDeployed(migrationMasterAddress); if (isDeployed) { setMigrationMasterDeployed(true); @@ -153,9 +158,44 @@ export function MigrationPopup({ }; const mintJettonsToMaster = async (connection: TonConnection) => { - // TODO - await new Promise((r) => setTimeout(r, 1000)); - setMintedJettonsToMaster(true); + const amount = totalSupply; + const parsedJettonMaster = Address.parse(jettonAddress!); + const migrationMasterConfig: MigrationMasterConfig = { + oldJettonMinter: parsedJettonMaster, + newJettonMinter: Address.parse(newMinterAddress), + }; + const params = { + code: MIGRATION_MASTER_CODE, + data: await migrationMasterConfigToCell(migrationMasterConfig), + deployer: Address.parse(address!), + value: MIGRATION_MASTER_DEPLOY_GAS, + }; + const migrationMasterAddress = new ContractDeployer().addressForContract(params); + + const newMinterJettonWalletAddress = await makeGetCall( + Address.parse(newMinterAddress), + "get_wallet_address", + [beginCell().storeAddress(Address.parse(address!)).endCell()], + ([addressCell]) => cellToAddress(addressCell), + await getClient(), + ); + + try { + const connection = WalletConnection.getConnection(); + await jettonDeployController.transfer( + connection, + amount!, + migrationMasterAddress.toFriendly(), + address!, + newMinterJettonWalletAddress.toFriendly(), + ); + } catch (error) { + if (error instanceof Error) { + showNotification(error.message, "error"); + } + } finally { + setMintedJettonsToMaster(true); + } }; interface TransactionStepProps { diff --git a/src/store/jetton-store/useJettonStore.ts b/src/store/jetton-store/useJettonStore.ts index 19d2027..4116a56 100644 --- a/src/store/jetton-store/useJettonStore.ts +++ b/src/store/jetton-store/useJettonStore.ts @@ -180,6 +180,8 @@ function useJettonStore() { }; }); + console.log(address); + if (address) { const minterParams: JettonDeployParams = { owner: Address.parse(address), @@ -194,10 +196,14 @@ function useJettonStore() { }; const minterDeployParams = createDeployParams(minterParams); const newMinterAddress = new ContractDeployer().addressForContract(minterDeployParams); - const isNewMinterDeployed = WalletConnection.isContractDeployed(newMinterAddress); + console.log(newMinterAddress.toFriendly()); + const client = await getClient(); + const isNewMinterDeployed = await client.isContractDeployed(newMinterAddress); let isMigrationMasterDeployed = false; let mintedJettonsToMaster = false; + console.log(isNewMinterDeployed); + if (isNewMinterDeployed) { const migrationMasterConfig: MigrationMasterConfig = { oldJettonMinter: parsedJettonMaster, @@ -209,12 +215,14 @@ function useJettonStore() { deployer: Address.parse(address), //anything value: new BN(0), //anything }); - isMigrationMasterDeployed = WalletConnection.isContractDeployed(migrationMasterAddress); + isMigrationMasterDeployed = await client.isContractDeployed(migrationMasterAddress); + + console.log(isMigrationMasterDeployed); if (isMigrationMasterDeployed) { const result = await jettonDeployController.getJettonDetails( newMinterAddress, - Address.parse(address), + migrationMasterAddress, connection, ); @@ -223,6 +231,8 @@ function useJettonStore() { return; } + console.log("qwe", result.jettonWallet?.jWalletAddress.toFriendly()); + const migrationMasterJettonBalance = result.jettonWallet?.balance; if (migrationMasterJettonBalance?.gt(new BN(0))) { From 6db5019ba579f913f783fc81bc91ac29a7ee9f0c Mon Sep 17 00:00:00 2001 From: Gusarich Date: Sat, 1 Jul 2023 09:12:48 +0300 Subject: [PATCH 23/30] remove the "New version" button and create a new pop-up window for user-side migration --- src/App.tsx | 1 + src/consts.ts | 1 + src/pages/jetton/dataRow/token/Token.tsx | 71 +++-- src/pages/jetton/userMigration.tsx | 342 +++++++++++++++++++++++ src/store/jetton-store/index.ts | 2 + src/store/jetton-store/useJettonStore.ts | 26 +- 6 files changed, 396 insertions(+), 47 deletions(-) create mode 100644 src/pages/jetton/userMigration.tsx diff --git a/src/App.tsx b/src/App.tsx index 0eb1d33..8cc976b 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -115,6 +115,7 @@ const App = () => { }> } /> } /> + } /> diff --git a/src/consts.ts b/src/consts.ts index a494332..f114a13 100644 --- a/src/consts.ts +++ b/src/consts.ts @@ -3,6 +3,7 @@ const ROUTES = { deployer: "/", jetton: "/jetton", jettonId: "/jetton/:id", + migration: "/jetton/:id/migration/:migrationId", }; const APP_GRID = 1156; diff --git a/src/pages/jetton/dataRow/token/Token.tsx b/src/pages/jetton/dataRow/token/Token.tsx index 1570a21..4c85417 100644 --- a/src/pages/jetton/dataRow/token/Token.tsx +++ b/src/pages/jetton/dataRow/token/Token.tsx @@ -28,6 +28,7 @@ import { AppButton } from "components/appButton"; import pen from "assets/icons/pen.svg"; import { CenteringWrapper } from "components/footer/styled"; import { MigrationPopup } from "pages/jetton/migration"; +import { UserMigrationPopup } from "pages/jetton/userMigration"; import { useNavigate } from "react-router-dom"; export const Token = () => { @@ -53,11 +54,15 @@ export const Token = () => { isMigrationMasterDeployed, mintedJettonsToMaster, newMinterAddress, + migrationId, } = useJettonStore(); const [openEdit, setOpenEdit] = useState(false); const [openMigrationPopup, setOpenMigrationPopup] = useState(false); + const [openUserMigrationPopup, setOpenUserMigrationPopup] = useState(false); const navigate = useNavigate(); + const isMigrationRoute: boolean = !!migrationId; + return ( {!openEdit ? ( @@ -113,52 +118,58 @@ export const Token = () => { )} - - { - /* isAdmin && */ isCodeOld && - !jettonLoading && - selectedWalletAddress && - !(isNewMinterDeployed && isMigrationMasterDeployed && mintedJettonsToMaster) && ( - - setOpenMigrationPopup(true)}> - - Pen Icon - Migration - - - - ) - } - {isNewMinterDeployed && isMigrationMasterDeployed && mintedJettonsToMaster && ( + {isMigrationRoute && !jettonLoading && ( navigate(`/jetton/${newMinterAddress}`)}> + onClick={() => setOpenUserMigrationPopup(true)}> New Button Icon - New version + Migration )} + {isMigrationRoute && !jettonLoading && ( + + )} + + {isCodeOld && + !jettonLoading && + selectedWalletAddress && + !(isNewMinterDeployed && isMigrationMasterDeployed && mintedJettonsToMaster) && ( + + setOpenMigrationPopup(true)}> + + Pen Icon + Migration + + + + )} {!isAdmin && isJettonDeployerFaultyOnChainData && ( diff --git a/src/pages/jetton/userMigration.tsx b/src/pages/jetton/userMigration.tsx new file mode 100644 index 0000000..237596e --- /dev/null +++ b/src/pages/jetton/userMigration.tsx @@ -0,0 +1,342 @@ +import useJettonStore from "store/jetton-store/useJettonStore"; +import { AppButton } from "components/appButton"; +import { CenteringWrapper } from "components/footer/styled"; +import { Popup } from "components/Popup"; +import { Typography } from "@mui/material"; +import bullet from "assets/icons/bullet.svg"; +import { Box } from "@mui/system"; +import CircularProgress from "@mui/material/CircularProgress"; +import CheckCircleIcon from "@mui/icons-material/CheckCircle"; +import { useNavigate } from "react-router-dom"; +import WalletConnection from "services/wallet-connection"; +import useConnectionStore from "store/connection-store/useConnectionStore"; +import { TonConnection } from "@ton-defi.org/ton-connection"; +import { Address, Cell, beginCell } from "ton"; +import { JettonDeployParams, jettonDeployController } from "lib/deploy-controller"; +import { createDeployParams } from "lib/utils"; +import BN from "bn.js"; +import { ContractDeployer } from "lib/contract-deployer"; +import { toDecimalsBN } from "utils"; +import analytics from "services/analytics"; +import useNotification from "hooks/useNotification"; +import { + MIGRATION_MASTER_CODE, + MIGRATION_MASTER_DEPLOY_GAS, + MigrationMasterConfig, + createMigrationMaster, + migrationMasterConfigToCell, +} from "lib/migrations"; +import { useJettonAddress } from "hooks/useJettonAddress"; +import { transfer } from "lib/jetton-minter"; +import { cellToAddress, makeGetCall } from "lib/make-get-call"; +import { getClient } from "lib/get-ton-client"; + +export function UserMigrationPopup({ + open, + setOpen, + jettonMinter, + migrationMaster, +}: { + open: boolean; + setOpen: (arg0: boolean) => void; + jettonMinter: string; + migrationMaster: string; +}) { + const { + symbol, + isNewMinterDeployed, + isMigrationMasterDeployed, + mintedJettonsToMaster, + migrationStarted, + newMinterAddress, + decimals, + name, + jettonImage, + description, + totalSupply, + balance, + jettonWalletAddress, + setNewMinterDeployed, + setMigrationMasterDeployed, + setMintedJettonsToMaster, + setMigrationStarted, + } = useJettonStore(); + const { address } = useConnectionStore(); + const { showNotification } = useNotification(); + const { jettonAddress } = useJettonAddress(); + + const navigate = useNavigate(); + + const onClose = () => { + setOpen(false); + }; + + const onSubmit = async () => { + const connection = WalletConnection.getConnection(); + if (!address || !connection) { + throw new Error("Wallet not connected"); + } + setMigrationStarted(true); + if (!isNewMinterDeployed) await deployNewJetton(connection); + if (!isMigrationMasterDeployed) await deployMigrationMaster(connection); + if (!mintedJettonsToMaster) await mintJettonsToMaster(connection); + }; + + const deployNewJetton = async (connection: TonConnection) => { + if (!address || !connection) { + throw new Error("Wallet not connected"); + } + + const params: JettonDeployParams = { + owner: Address.parse(address), + onchainMetaData: { + name: name!, + symbol: symbol!, + image: jettonImage, + description: description, + decimals: parseInt(decimals!).toFixed(0), + }, + amountToMint: totalSupply!, + }; + + const deployParams = createDeployParams(params); + const contractAddress = new ContractDeployer().addressForContract(deployParams); + + const client = await getClient(); + const isDeployed = await client.isContractDeployed(contractAddress); + + if (isDeployed) { + setNewMinterDeployed(true); + return; + } + + try { + const result = await jettonDeployController.createJetton(params, connection); + } catch (err) { + if (err instanceof Error) { + showNotification(<>{err.message}, "error"); + } + } finally { + setNewMinterDeployed(true); + } + }; + + const deployMigrationMaster = async (connection: TonConnection) => { + if (!address || !connection) { + throw new Error("Wallet not connected"); + } + + const parsedJettonMaster = Address.parse(jettonAddress!); + + const migrationMasterConfig: MigrationMasterConfig = { + oldJettonMinter: parsedJettonMaster, + newJettonMinter: Address.parse(newMinterAddress), + }; + const params = { + code: MIGRATION_MASTER_CODE, + data: await migrationMasterConfigToCell(migrationMasterConfig), + deployer: Address.parse(address), + value: MIGRATION_MASTER_DEPLOY_GAS, + }; + const migrationMasterAddress = new ContractDeployer().addressForContract(params); + const client = await getClient(); + const isDeployed = await client.isContractDeployed(migrationMasterAddress); + + if (isDeployed) { + setMigrationMasterDeployed(true); + return; + } + + try { + const result = await createMigrationMaster( + migrationMasterConfig, + connection, + Address.parse(address), + ); + } catch (err) { + if (err instanceof Error) { + showNotification(<>{err.message}, "error"); + } + } finally { + setMigrationMasterDeployed(true); + } + }; + + const mintJettonsToMaster = async (connection: TonConnection) => { + const amount = totalSupply; + const parsedJettonMaster = Address.parse(jettonAddress!); + const migrationMasterConfig: MigrationMasterConfig = { + oldJettonMinter: parsedJettonMaster, + newJettonMinter: Address.parse(newMinterAddress), + }; + const params = { + code: MIGRATION_MASTER_CODE, + data: await migrationMasterConfigToCell(migrationMasterConfig), + deployer: Address.parse(address!), + value: MIGRATION_MASTER_DEPLOY_GAS, + }; + const migrationMasterAddress = new ContractDeployer().addressForContract(params); + + const newMinterJettonWalletAddress = await makeGetCall( + Address.parse(newMinterAddress), + "get_wallet_address", + [beginCell().storeAddress(Address.parse(address!)).endCell()], + ([addressCell]) => cellToAddress(addressCell), + await getClient(), + ); + + try { + const connection = WalletConnection.getConnection(); + await jettonDeployController.transfer( + connection, + amount!, + migrationMasterAddress.toFriendly(), + address!, + newMinterJettonWalletAddress.toFriendly(), + ); + } catch (error) { + if (error instanceof Error) { + showNotification(error.message, "error"); + } + } finally { + setMintedJettonsToMaster(true); + } + }; + + interface TransactionStepProps { + spinning: boolean; + description: string; + } + + const TransactionStep: React.FC = ({ spinning, description }) => ( + + + {description} + + ); + + const TransactionProgress = () => { + return ( +
+ + Migration process + + + + Do not close this page until you finish the process. + + + + + +
+ ); + }; + + return ( + + {!migrationStarted ? ( + <> + + + Initiate migration + + + This operation will initiate the migration process of the
token{" "} + {symbol}. This means: +
+
    +
  • + + You should only migrate your tokens if it is neccessary + +
  • +
  • + + You will lose all your old {symbol} + +
  • +
  • + + You will receive exactly{" "} + {balance?.toString()} tokens in the new + version of {symbol}{" "} + +
  • +
  • + + You will not be able to get back to the old version + +
  • +
+ + You should consider these points before initiating the migration. + +
+ + + onClose()}> + Cancel + + + { + onSubmit(); + }}> + Migration + + + + ) : ( + <> + + {isNewMinterDeployed && isMigrationMasterDeployed && mintedJettonsToMaster && ( + { + onClose(); + navigate(`/jetton/${newMinterAddress}`); + }}> + Go to the new Jetton + + )} + + )} +
+ ); +} + +function Spinner({ spinning }: { spinning: boolean }) { + return ( + + {spinning ? : } + + ); +} diff --git a/src/store/jetton-store/index.ts b/src/store/jetton-store/index.ts index 8c95014..2d71cbc 100644 --- a/src/store/jetton-store/index.ts +++ b/src/store/jetton-store/index.ts @@ -27,6 +27,7 @@ export interface JettonStoreState { mintedJettonsToMaster: boolean; migrationStarted: boolean; newMinterAddress: string; + migrationId?: string; } const jettonStateAtom = atom({ @@ -56,6 +57,7 @@ const jettonStateAtom = atom({ mintedJettonsToMaster: false, migrationStarted: false, newMinterAddress: "", + migrationId: "", }, }); diff --git a/src/store/jetton-store/useJettonStore.ts b/src/store/jetton-store/useJettonStore.ts index 4116a56..ad5e19a 100644 --- a/src/store/jetton-store/useJettonStore.ts +++ b/src/store/jetton-store/useJettonStore.ts @@ -20,6 +20,7 @@ import { migrationMasterConfigToCell, } from "lib/migrations"; import { getClient } from "lib/get-ton-client"; +import { useParams } from "react-router-dom"; function useJettonStore() { const [state, setState] = useRecoilState(jettonStateAtom); @@ -27,6 +28,7 @@ function useJettonStore() { const { showNotification } = useNotification(); const { address: connectedWalletAddress } = useConnectionStore(); const { jettonAddress } = useJettonAddress(); + const { migrationId }: { migrationId?: string } = useParams(); const setNewMinterDeployed = useCallback( (newValue: boolean) => { @@ -180,8 +182,6 @@ function useJettonStore() { }; }); - console.log(address); - if (address) { const minterParams: JettonDeployParams = { owner: Address.parse(address), @@ -196,14 +196,12 @@ function useJettonStore() { }; const minterDeployParams = createDeployParams(minterParams); const newMinterAddress = new ContractDeployer().addressForContract(minterDeployParams); - console.log(newMinterAddress.toFriendly()); + const client = await getClient(); const isNewMinterDeployed = await client.isContractDeployed(newMinterAddress); let isMigrationMasterDeployed = false; let mintedJettonsToMaster = false; - console.log(isNewMinterDeployed); - if (isNewMinterDeployed) { const migrationMasterConfig: MigrationMasterConfig = { oldJettonMinter: parsedJettonMaster, @@ -217,8 +215,6 @@ function useJettonStore() { }); isMigrationMasterDeployed = await client.isContractDeployed(migrationMasterAddress); - console.log(isMigrationMasterDeployed); - if (isMigrationMasterDeployed) { const result = await jettonDeployController.getJettonDetails( newMinterAddress, @@ -226,17 +222,12 @@ function useJettonStore() { connection, ); - if (!result) { - console.log("empty"); - return; - } - - console.log("qwe", result.jettonWallet?.jWalletAddress.toFriendly()); - - const migrationMasterJettonBalance = result.jettonWallet?.balance; + if (result) { + const migrationMasterJettonBalance = result.jettonWallet?.balance; - if (migrationMasterJettonBalance?.gt(new BN(0))) { - mintedJettonsToMaster = true; + if (migrationMasterJettonBalance?.gt(new BN(0))) { + mintedJettonsToMaster = true; + } } } } @@ -268,6 +259,7 @@ function useJettonStore() { return { ...state, + migrationId, getJettonDetails, reset, setNewMinterDeployed, From 0be6d4930be36cb98bd3894fc80a86f5454d8430 Mon Sep 17 00:00:00 2001 From: Gusarich Date: Sun, 2 Jul 2023 12:52:51 +0300 Subject: [PATCH 24/30] wip: actually working user migraiton interface --- src/lib/migrations.ts | 33 ++++++ src/pages/jetton/dataRow/token/Token.tsx | 17 ++- src/pages/jetton/userMigration.tsx | 136 ++++++----------------- src/store/jetton-store/index.ts | 8 ++ src/store/jetton-store/useJettonStore.ts | 64 ++++++++++- 5 files changed, 148 insertions(+), 110 deletions(-) diff --git a/src/lib/migrations.ts b/src/lib/migrations.ts index 217a89d..e1be2cc 100644 --- a/src/lib/migrations.ts +++ b/src/lib/migrations.ts @@ -17,6 +17,7 @@ enum OPS { } export const MIGRATION_MASTER_DEPLOY_GAS = new BN("100000000"); +export const MIGRATION_HELPER_DEPLOY_GAS = new BN("20000000"); export type MigrationMasterConfig = { oldJettonMinter: Address; @@ -102,3 +103,35 @@ export async function createMigrationMaster( return migrationMasterAddress; } + +export async function createMigrationHelper( + config: MigrationHelperConfig, + tonConnection: TonConnection, + owner: Address, +): Promise
{ + const contractDeployer = new ContractDeployer(); + const tc = await getClient(); + + // params.onProgress?.(JettonDeployState.BALANCE_CHECK); + const balance = await tc.getBalance(owner); + if (balance.lt(MIGRATION_HELPER_DEPLOY_GAS)) + throw new Error("Not enough balance in deployer wallet"); + const params = { + code: MIGRATION_HELPER_CODE, + data: await migrationHelperConfigToCell(config), + deployer: owner, //anything + value: MIGRATION_HELPER_DEPLOY_GAS, + }; + const migrationHelperAddress = new ContractDeployer().addressForContract(params); + const isDeployed = tc.isContractDeployed(migrationHelperAddress); + + if (await tc.isContractDeployed(migrationHelperAddress)) { + // params.onProgress?.(JettonDeployState.ALREADY_DEPLOYED); + } else { + await contractDeployer.deployContract(params, tonConnection); + // params.onProgress?.(JettonDeployState.AWAITING_MINTER_DEPLOY); + await waitForContractDeploy(migrationHelperAddress, tc); + } + + return migrationHelperAddress; +} diff --git a/src/pages/jetton/dataRow/token/Token.tsx b/src/pages/jetton/dataRow/token/Token.tsx index 4c85417..52696d8 100644 --- a/src/pages/jetton/dataRow/token/Token.tsx +++ b/src/pages/jetton/dataRow/token/Token.tsx @@ -138,16 +138,15 @@ export const Token = () => { )} - {isMigrationRoute && !jettonLoading && ( - - )} + - {isCodeOld && + {!isMigrationRoute && + isCodeOld && !jettonLoading && selectedWalletAddress && !(isNewMinterDeployed && isMigrationMasterDeployed && mintedJettonsToMaster) && ( diff --git a/src/pages/jetton/userMigration.tsx b/src/pages/jetton/userMigration.tsx index 237596e..5981e86 100644 --- a/src/pages/jetton/userMigration.tsx +++ b/src/pages/jetton/userMigration.tsx @@ -13,17 +13,22 @@ import useConnectionStore from "store/connection-store/useConnectionStore"; import { TonConnection } from "@ton-defi.org/ton-connection"; import { Address, Cell, beginCell } from "ton"; import { JettonDeployParams, jettonDeployController } from "lib/deploy-controller"; -import { createDeployParams } from "lib/utils"; +import { createDeployParams, sleep } from "lib/utils"; import BN from "bn.js"; import { ContractDeployer } from "lib/contract-deployer"; import { toDecimalsBN } from "utils"; import analytics from "services/analytics"; import useNotification from "hooks/useNotification"; import { + MIGRATION_HELPER_CODE, + MIGRATION_HELPER_DEPLOY_GAS, MIGRATION_MASTER_CODE, MIGRATION_MASTER_DEPLOY_GAS, + MigrationHelperConfig, MigrationMasterConfig, + createMigrationHelper, createMigrationMaster, + migrationHelperConfigToCell, migrationMasterConfigToCell, } from "lib/migrations"; import { useJettonAddress } from "hooks/useJettonAddress"; @@ -56,10 +61,17 @@ export function UserMigrationPopup({ totalSupply, balance, jettonWalletAddress, + isMigrationHelperDeployed, + migrationHelperBalance, + migrationHelper, + transferredJettonsToHelper, setNewMinterDeployed, setMigrationMasterDeployed, setMintedJettonsToMaster, setMigrationStarted, + setMigrationHelperDeployed, + setMigrationHelperBalance, + setTransferredJettonsToHelper, } = useJettonStore(); const { address } = useConnectionStore(); const { showNotification } = useNotification(); @@ -77,79 +89,40 @@ export function UserMigrationPopup({ throw new Error("Wallet not connected"); } setMigrationStarted(true); - if (!isNewMinterDeployed) await deployNewJetton(connection); - if (!isMigrationMasterDeployed) await deployMigrationMaster(connection); - if (!mintedJettonsToMaster) await mintJettonsToMaster(connection); + if (!isMigrationHelperDeployed) await deployMigrationHelper(connection); + await transferJettonsToHelper(connection); }; - const deployNewJetton = async (connection: TonConnection) => { - if (!address || !connection) { - throw new Error("Wallet not connected"); - } - - const params: JettonDeployParams = { - owner: Address.parse(address), - onchainMetaData: { - name: name!, - symbol: symbol!, - image: jettonImage, - description: description, - decimals: parseInt(decimals!).toFixed(0), - }, - amountToMint: totalSupply!, - }; - - const deployParams = createDeployParams(params); - const contractAddress = new ContractDeployer().addressForContract(deployParams); - - const client = await getClient(); - const isDeployed = await client.isContractDeployed(contractAddress); - - if (isDeployed) { - setNewMinterDeployed(true); - return; - } - - try { - const result = await jettonDeployController.createJetton(params, connection); - } catch (err) { - if (err instanceof Error) { - showNotification(<>{err.message}, "error"); - } - } finally { - setNewMinterDeployed(true); - } - }; - - const deployMigrationMaster = async (connection: TonConnection) => { + const deployMigrationHelper = async (connection: TonConnection) => { if (!address || !connection) { throw new Error("Wallet not connected"); } const parsedJettonMaster = Address.parse(jettonAddress!); - const migrationMasterConfig: MigrationMasterConfig = { + const migrationHelperConfig: MigrationHelperConfig = { oldJettonMinter: parsedJettonMaster, - newJettonMinter: Address.parse(newMinterAddress), + migrationMaster: Address.parse(migrationMaster), + recipient: Address.parse(address), }; const params = { - code: MIGRATION_MASTER_CODE, - data: await migrationMasterConfigToCell(migrationMasterConfig), + code: MIGRATION_HELPER_CODE, + data: await migrationHelperConfigToCell(migrationHelperConfig), deployer: Address.parse(address), - value: MIGRATION_MASTER_DEPLOY_GAS, + value: MIGRATION_HELPER_DEPLOY_GAS, }; - const migrationMasterAddress = new ContractDeployer().addressForContract(params); + const migrationHelperAddress = new ContractDeployer().addressForContract(params); const client = await getClient(); - const isDeployed = await client.isContractDeployed(migrationMasterAddress); + const isDeployed = await client.isContractDeployed(migrationHelperAddress); if (isDeployed) { - setMigrationMasterDeployed(true); + setMigrationHelperDeployed(true); return; } try { - const result = await createMigrationMaster( - migrationMasterConfig, + const result = await createMigrationHelper( + migrationHelperConfig, connection, Address.parse(address), ); @@ -158,49 +131,13 @@ export function UserMigrationPopup({ showNotification(<>{err.message}, "error"); } } finally { - setMigrationMasterDeployed(true); + setMigrationHelperDeployed(true); } }; - const mintJettonsToMaster = async (connection: TonConnection) => { - const amount = totalSupply; - const parsedJettonMaster = Address.parse(jettonAddress!); - const migrationMasterConfig: MigrationMasterConfig = { - oldJettonMinter: parsedJettonMaster, - newJettonMinter: Address.parse(newMinterAddress), - }; - const params = { - code: MIGRATION_MASTER_CODE, - data: await migrationMasterConfigToCell(migrationMasterConfig), - deployer: Address.parse(address!), - value: MIGRATION_MASTER_DEPLOY_GAS, - }; - const migrationMasterAddress = new ContractDeployer().addressForContract(params); - - const newMinterJettonWalletAddress = await makeGetCall( - Address.parse(newMinterAddress), - "get_wallet_address", - [beginCell().storeAddress(Address.parse(address!)).endCell()], - ([addressCell]) => cellToAddress(addressCell), - await getClient(), - ); - - try { - const connection = WalletConnection.getConnection(); - await jettonDeployController.transfer( - connection, - amount!, - migrationMasterAddress.toFriendly(), - address!, - newMinterJettonWalletAddress.toFriendly(), - ); - } catch (error) { - if (error instanceof Error) { - showNotification(error.message, "error"); - } - } finally { - setMintedJettonsToMaster(true); - } + const transferJettonsToHelper = async (connection: TonConnection) => { + await sleep(1000); + setTransferredJettonsToHelper(true); }; interface TransactionStepProps { @@ -233,14 +170,13 @@ export function UserMigrationPopup({ Do not close this page until you finish the process. -
); @@ -317,7 +253,7 @@ export function UserMigrationPopup({ ) : ( <> - {isNewMinterDeployed && isMigrationMasterDeployed && mintedJettonsToMaster && ( + {isMigrationHelperDeployed && transferredJettonsToHelper && ( { diff --git a/src/store/jetton-store/index.ts b/src/store/jetton-store/index.ts index 2d71cbc..ff8ee37 100644 --- a/src/store/jetton-store/index.ts +++ b/src/store/jetton-store/index.ts @@ -28,6 +28,10 @@ export interface JettonStoreState { migrationStarted: boolean; newMinterAddress: string; migrationId?: string; + migrationHelper?: string; + migrationHelperBalance?: BN; + isMigrationHelperDeployed: boolean; + transferredJettonsToHelper: boolean; } const jettonStateAtom = atom({ @@ -58,6 +62,10 @@ const jettonStateAtom = atom({ migrationStarted: false, newMinterAddress: "", migrationId: "", + migrationHelper: "", + migrationHelperBalance: undefined, + isMigrationHelperDeployed: false, + transferredJettonsToHelper: false, }, }); diff --git a/src/store/jetton-store/useJettonStore.ts b/src/store/jetton-store/useJettonStore.ts index ad5e19a..2292f87 100644 --- a/src/store/jetton-store/useJettonStore.ts +++ b/src/store/jetton-store/useJettonStore.ts @@ -12,11 +12,14 @@ import useConnectionStore from "store/connection-store/useConnectionStore"; import { getUrlParam, isValidAddress } from "utils"; import { useJettonAddress } from "hooks/useJettonAddress"; import { JETTON_MINTER_CODE } from "lib/jetton-minter"; -import { BN } from "bn.js"; +import BN from "bn.js"; import { ContractDeployer } from "lib/contract-deployer"; import { + MIGRATION_HELPER_CODE, MIGRATION_MASTER_CODE, + MigrationHelperConfig, MigrationMasterConfig, + migrationHelperConfigToCell, migrationMasterConfigToCell, } from "lib/migrations"; import { getClient } from "lib/get-ton-client"; @@ -70,6 +73,36 @@ function useJettonStore() { [setState], ); + const setMigrationHelperBalance = useCallback( + (newValue: BN) => { + setState((prevState) => ({ + ...prevState, + migrationHelperBalance: newValue, + })); + }, + [setState], + ); + + const setMigrationHelperDeployed = useCallback( + (newValue: boolean) => { + setState((prevState) => ({ + ...prevState, + isMigrationHelperDeployed: newValue, + })); + }, + [setState], + ); + + const setTransferredJettonsToHelper = useCallback( + (newValue: boolean) => { + setState((prevState) => ({ + ...prevState, + transferredJettonsToHelper: newValue, + })); + }, + [setState], + ); + const getJettonDetails = useCallback(async () => { let queryAddress = getUrlParam("address"); @@ -232,12 +265,38 @@ function useJettonStore() { } } + let migrationHelperAddress: Address; + let isMigrationHelperDeployed: boolean; + let migrationHelperBalance: BN; + + if (migrationId) { + const migrationHelperConfig: MigrationHelperConfig = { + oldJettonMinter: parsedJettonMaster, + migrationMaster: Address.parse(migrationId), + recipient: Address.parse(address), + }; + migrationHelperAddress = new ContractDeployer().addressForContract({ + code: MIGRATION_HELPER_CODE, + data: await migrationHelperConfigToCell(migrationHelperConfig), + deployer: Address.parse(address), //anything + value: new BN(0), //anything + }); + isMigrationHelperDeployed = await client.isContractDeployed(migrationHelperAddress); + + if (isMigrationHelperDeployed) { + migrationHelperBalance = await client.getBalance(migrationHelperAddress); + } + } + setState((prevState) => ({ ...prevState, isNewMinterDeployed, newMinterAddress: newMinterAddress.toString(), isMigrationMasterDeployed, mintedJettonsToMaster, + migrationHelper: migrationHelperAddress.toString(), + isMigrationHelperDeployed, + migrationHelperBalance, })); } } catch (error) { @@ -266,6 +325,9 @@ function useJettonStore() { setMigrationMasterDeployed, setMintedJettonsToMaster, setMigrationStarted, + setMigrationHelperDeployed, + setMigrationHelperBalance, + setTransferredJettonsToHelper, }; } From 9a9bc0d8267d2562da96fcfea23bbe91a11a4a9e Mon Sep 17 00:00:00 2001 From: Gusarich Date: Sun, 2 Jul 2023 14:44:23 +0300 Subject: [PATCH 25/30] actually deploy migration helper --- src/lib/contract-deployer.ts | 2 +- src/lib/migrations.ts | 11 +++++++++-- src/pages/jetton/userMigration.tsx | 9 +++++++++ src/store/jetton-store/useJettonStore.ts | 2 +- 4 files changed, 20 insertions(+), 4 deletions(-) diff --git a/src/lib/contract-deployer.ts b/src/lib/contract-deployer.ts index 34d1a9a..fffbc94 100644 --- a/src/lib/contract-deployer.ts +++ b/src/lib/contract-deployer.ts @@ -13,7 +13,7 @@ interface ContractDeployDetails { export class ContractDeployer { addressForContract(params: ContractDeployDetails) { - console.log(params.data, params.code); + console.log(77, params.data, params.code); return contractAddress({ workchain: 0, initialData: params.data, diff --git a/src/lib/migrations.ts b/src/lib/migrations.ts index e1be2cc..2201caa 100644 --- a/src/lib/migrations.ts +++ b/src/lib/migrations.ts @@ -58,8 +58,12 @@ export type MigrationHelperConfig = { export async function migrationHelperConfigToCell(config: MigrationHelperConfig): Promise { const client = await getClient(); - const oldWalletCode = (await client.callGetMethod(config.oldJettonMinter, "get_jetton_data")) - .stack[4]; + const oldWalletCode = Cell.fromBoc( + Buffer.from( + (await client.callGetMethod(config.oldJettonMinter, "get_jetton_data")).stack[4][1].bytes, + "base64", + ).toString("hex"), + )[0]; return beginCell() .storeAddress(config.oldJettonMinter) .storeAddress(config.migrationMaster) @@ -128,9 +132,12 @@ export async function createMigrationHelper( if (await tc.isContractDeployed(migrationHelperAddress)) { // params.onProgress?.(JettonDeployState.ALREADY_DEPLOYED); } else { + console.log(123); await contractDeployer.deployContract(params, tonConnection); + console.log(123); // params.onProgress?.(JettonDeployState.AWAITING_MINTER_DEPLOY); await waitForContractDeploy(migrationHelperAddress, tc); + console.log(123); } return migrationHelperAddress; diff --git a/src/pages/jetton/userMigration.tsx b/src/pages/jetton/userMigration.tsx index 5981e86..4cca395 100644 --- a/src/pages/jetton/userMigration.tsx +++ b/src/pages/jetton/userMigration.tsx @@ -98,22 +98,31 @@ export function UserMigrationPopup({ throw new Error("Wallet not connected"); } + console.log(jettonAddress!, migrationMaster); + const parsedJettonMaster = Address.parse(jettonAddress!); + console.log(123); + const migrationHelperConfig: MigrationHelperConfig = { oldJettonMinter: parsedJettonMaster, migrationMaster: Address.parse(migrationMaster), recipient: Address.parse(address), }; + console.log(123, address, MIGRATION_HELPER_CODE); const params = { code: MIGRATION_HELPER_CODE, data: await migrationHelperConfigToCell(migrationHelperConfig), deployer: Address.parse(address), value: MIGRATION_HELPER_DEPLOY_GAS, }; + console.log(123); const migrationHelperAddress = new ContractDeployer().addressForContract(params); + console.log(123); const client = await getClient(); + console.log(123); const isDeployed = await client.isContractDeployed(migrationHelperAddress); + console.log(123); if (isDeployed) { setMigrationHelperDeployed(true); diff --git a/src/store/jetton-store/useJettonStore.ts b/src/store/jetton-store/useJettonStore.ts index 2292f87..6f3f60a 100644 --- a/src/store/jetton-store/useJettonStore.ts +++ b/src/store/jetton-store/useJettonStore.ts @@ -294,7 +294,7 @@ function useJettonStore() { newMinterAddress: newMinterAddress.toString(), isMigrationMasterDeployed, mintedJettonsToMaster, - migrationHelper: migrationHelperAddress.toString(), + migrationHelper: migrationHelperAddress ? migrationHelperAddress.toString() : undefined, isMigrationHelperDeployed, migrationHelperBalance, })); From 1d456f7633d3e15aad95cca1cf2f2b8e1d984148 Mon Sep 17 00:00:00 2001 From: Gusarich Date: Sun, 2 Jul 2023 14:49:54 +0300 Subject: [PATCH 26/30] fix display of the amount --- src/pages/jetton/userMigration.tsx | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/pages/jetton/userMigration.tsx b/src/pages/jetton/userMigration.tsx index 4cca395..6889392 100644 --- a/src/pages/jetton/userMigration.tsx +++ b/src/pages/jetton/userMigration.tsx @@ -35,6 +35,7 @@ import { useJettonAddress } from "hooks/useJettonAddress"; import { transfer } from "lib/jetton-minter"; import { cellToAddress, makeGetCall } from "lib/make-get-call"; import { getClient } from "lib/get-ton-client"; +import BigNumberDisplay from "components/BigNumberDisplay"; export function UserMigrationPopup({ open, @@ -229,9 +230,11 @@ export function UserMigrationPopup({
  • - You will receive exactly{" "} - {balance?.toString()} tokens in the new - version of {symbol}{" "} + You will receive{" "} + + + {" "} + tokens in the new version of {symbol}{" "}
  • From 84979b8fc4330c6e685cacb3873d5715f38be27f Mon Sep 17 00:00:00 2001 From: Gusarich Date: Sun, 2 Jul 2023 15:10:01 +0300 Subject: [PATCH 27/30] migration is working correctly. todo: fix little bugs --- src/lib/deploy-controller.ts | 11 +++++++++-- src/lib/jetton-minter.ts | 9 +++++++-- src/pages/jetton/userMigration.tsx | 23 +++++++++++++++++++++-- 3 files changed, 37 insertions(+), 6 deletions(-) diff --git a/src/lib/deploy-controller.ts b/src/lib/deploy-controller.ts index eade0ab..5f1dd3b 100644 --- a/src/lib/deploy-controller.ts +++ b/src/lib/deploy-controller.ts @@ -124,6 +124,8 @@ class JettonDeployController { toAddress: string, fromAddress: string, ownerJettonWallet: string, + customValue?: number, + customForwardValue?: number, ) { const { address } = await tonConnection.connect(); const tc = await getClient(); @@ -136,8 +138,13 @@ class JettonDeployController { await tonConnection.requestTransaction({ to: Address.parse(ownerJettonWallet), - value: toNano(0.05), - message: transfer(Address.parse(toAddress), Address.parse(fromAddress), amount), + value: toNano(customValue || 0.05), + message: transfer( + Address.parse(toAddress), + Address.parse(fromAddress), + amount, + customForwardValue, + ), }); await waiter(); diff --git a/src/lib/jetton-minter.ts b/src/lib/jetton-minter.ts index 231072d..066c1c6 100644 --- a/src/lib/jetton-minter.ts +++ b/src/lib/jetton-minter.ts @@ -235,7 +235,12 @@ export function burn(amount: BN, responseAddress: Address) { .endCell(); } -export function transfer(to: Address, from: Address, jettonAmount: BN) { +export function transfer( + to: Address, + from: Address, + jettonAmount: BN, + customForwardValue?: number, +) { return beginCell() .storeUint(OPS.Transfer, 32) .storeUint(1, 64) @@ -243,7 +248,7 @@ export function transfer(to: Address, from: Address, jettonAmount: BN) { .storeAddress(to) .storeAddress(from) .storeBit(false) - .storeCoins(toNano(0.001)) + .storeCoins(toNano(customForwardValue || 0.001)) .storeBit(false) // forward_payload in this slice, not separate cell .endCell(); } diff --git a/src/pages/jetton/userMigration.tsx b/src/pages/jetton/userMigration.tsx index 6889392..4fd41f3 100644 --- a/src/pages/jetton/userMigration.tsx +++ b/src/pages/jetton/userMigration.tsx @@ -146,8 +146,27 @@ export function UserMigrationPopup({ }; const transferJettonsToHelper = async (connection: TonConnection) => { - await sleep(1000); - setTransferredJettonsToHelper(true); + const amount = balance!; + const parsedJettonWallet = Address.parse(jettonWalletAddress!); + + try { + const connection = WalletConnection.getConnection(); + await jettonDeployController.transfer( + connection, + amount!, + migrationHelper!, + address!, + parsedJettonWallet.toFriendly(), + 0.35, + 0.3, + ); + } catch (error) { + if (error instanceof Error) { + showNotification(error.message, "error"); + } + } finally { + setTransferredJettonsToHelper(true); + } }; interface TransactionStepProps { From cc2db81852b8d9654387f5d7a595b8d50ed7dbb7 Mon Sep 17 00:00:00 2001 From: Gusarich Date: Sun, 2 Jul 2023 16:14:05 +0300 Subject: [PATCH 28/30] fixes --- src/lib/deploy-controller.ts | 10 +++--- src/lib/migrations.ts | 6 ++-- src/pages/deployer/index.tsx | 3 +- src/pages/jetton/migration.tsx | 40 +++++++++++------------- src/pages/jetton/userMigration.tsx | 13 ++++---- src/store/jetton-store/useJettonStore.ts | 6 ---- 6 files changed, 34 insertions(+), 44 deletions(-) diff --git a/src/lib/deploy-controller.ts b/src/lib/deploy-controller.ts index 5a26ff7..047c3cb 100644 --- a/src/lib/deploy-controller.ts +++ b/src/lib/deploy-controller.ts @@ -169,11 +169,11 @@ class JettonDeployController { amount: toNano(customValue || 0.05).toString(), stateInit: undefined, payload: transfer( - Address.parse(toAddress), - Address.parse(fromAddress), - amount, - customForwardValue, - ) + Address.parse(toAddress), + Address.parse(fromAddress), + amount, + customForwardValue, + ) .toBoc() .toString("base64"), }, diff --git a/src/lib/migrations.ts b/src/lib/migrations.ts index 2201caa..9f61e13 100644 --- a/src/lib/migrations.ts +++ b/src/lib/migrations.ts @@ -2,9 +2,9 @@ import { Cell, beginCell, Address, TonClient } from "ton"; import masterHex from "./contracts/MigrationMaster.compiled.json"; import helperHex from "./contracts/MigrationHelper.compiled.json"; +import { useTonAddress, useTonConnectUI, TonConnectUI } from "@tonconnect/ui-react"; import { getClient } from "./get-ton-client"; import BN from "bn.js"; -import { TonConnection } from "@ton-defi.org/ton-connection"; import { ContractDeployer } from "./contract-deployer"; import WalletConnection from "services/wallet-connection"; import { waitForContractDeploy } from "./utils"; @@ -78,7 +78,7 @@ export function migrateBody(amount: BN): Cell { export async function createMigrationMaster( config: MigrationMasterConfig, - tonConnection: TonConnection, + tonConnection: TonConnectUI, owner: Address, ): Promise
    { const contractDeployer = new ContractDeployer(); @@ -110,7 +110,7 @@ export async function createMigrationMaster( export async function createMigrationHelper( config: MigrationHelperConfig, - tonConnection: TonConnection, + tonConnection: TonConnectUI, owner: Address, ): Promise
    { const contractDeployer = new ContractDeployer(); diff --git a/src/pages/deployer/index.tsx b/src/pages/deployer/index.tsx index 1e9d2da..8aa8058 100644 --- a/src/pages/deployer/index.tsx +++ b/src/pages/deployer/index.tsx @@ -73,8 +73,7 @@ function DeployerPage() { const deployParams = createDeployParams(params, data.offchainUri); const contractAddress = new ContractDeployer().addressForContract(deployParams); - const client = await getClient(); - const isDeployed = await client.isContractDeployed(contractAddress); + const isDeployed = await WalletConnection.isContractDeployed(contractAddress); if (isDeployed) { showNotification( diff --git a/src/pages/jetton/migration.tsx b/src/pages/jetton/migration.tsx index 84c2f8e..0174004 100644 --- a/src/pages/jetton/migration.tsx +++ b/src/pages/jetton/migration.tsx @@ -9,8 +9,6 @@ import CircularProgress from "@mui/material/CircularProgress"; import CheckCircleIcon from "@mui/icons-material/CheckCircle"; import { useNavigate } from "react-router-dom"; import WalletConnection from "services/wallet-connection"; -import useConnectionStore from "store/connection-store/useConnectionStore"; -import { TonConnection } from "@ton-defi.org/ton-connection"; import { Address, Cell, beginCell } from "ton"; import { JettonDeployParams, jettonDeployController } from "lib/deploy-controller"; import { createDeployParams } from "lib/utils"; @@ -19,6 +17,7 @@ import { ContractDeployer } from "lib/contract-deployer"; import { toDecimalsBN } from "utils"; import analytics from "services/analytics"; import useNotification from "hooks/useNotification"; +import { useTonAddress, useTonConnectUI, TonConnectUI } from "@tonconnect/ui-react"; import { MIGRATION_MASTER_CODE, MIGRATION_MASTER_DEPLOY_GAS, @@ -56,9 +55,10 @@ export function MigrationPopup({ setMintedJettonsToMaster, setMigrationStarted, } = useJettonStore(); - const { address } = useConnectionStore(); + const [tonconnect] = useTonConnectUI(); const { showNotification } = useNotification(); const { jettonAddress } = useJettonAddress(); + const walletAddress = useTonAddress(); const navigate = useNavigate(); @@ -67,23 +67,22 @@ export function MigrationPopup({ }; const onSubmit = async () => { - const connection = WalletConnection.getConnection(); - if (!address || !connection) { + if (!walletAddress || !tonconnect) { throw new Error("Wallet not connected"); } setMigrationStarted(true); - if (!isNewMinterDeployed) await deployNewJetton(connection); - if (!isMigrationMasterDeployed) await deployMigrationMaster(connection); - if (!mintedJettonsToMaster) await mintJettonsToMaster(connection); + if (!isNewMinterDeployed) await deployNewJetton(tonconnect); + if (!isMigrationMasterDeployed) await deployMigrationMaster(tonconnect); + if (!mintedJettonsToMaster) await mintJettonsToMaster(tonconnect); }; - const deployNewJetton = async (connection: TonConnection) => { - if (!address || !connection) { + const deployNewJetton = async (connection: TonConnectUI) => { + if (!walletAddress || !connection) { throw new Error("Wallet not connected"); } const params: JettonDeployParams = { - owner: Address.parse(address), + owner: Address.parse(walletAddress), onchainMetaData: { name: name!, symbol: symbol!, @@ -106,7 +105,7 @@ export function MigrationPopup({ } try { - const result = await jettonDeployController.createJetton(params, connection); + const result = await jettonDeployController.createJetton(params, connection, walletAddress); } catch (err) { if (err instanceof Error) { showNotification(<>{err.message}, "error"); @@ -116,8 +115,8 @@ export function MigrationPopup({ } }; - const deployMigrationMaster = async (connection: TonConnection) => { - if (!address || !connection) { + const deployMigrationMaster = async (connection: TonConnectUI) => { + if (!walletAddress || !connection) { throw new Error("Wallet not connected"); } @@ -130,7 +129,7 @@ export function MigrationPopup({ const params = { code: MIGRATION_MASTER_CODE, data: await migrationMasterConfigToCell(migrationMasterConfig), - deployer: Address.parse(address), + deployer: Address.parse(walletAddress), value: MIGRATION_MASTER_DEPLOY_GAS, }; const migrationMasterAddress = new ContractDeployer().addressForContract(params); @@ -146,7 +145,7 @@ export function MigrationPopup({ const result = await createMigrationMaster( migrationMasterConfig, connection, - Address.parse(address), + Address.parse(walletAddress), ); } catch (err) { if (err instanceof Error) { @@ -157,7 +156,7 @@ export function MigrationPopup({ } }; - const mintJettonsToMaster = async (connection: TonConnection) => { + const mintJettonsToMaster = async (connection: TonConnectUI) => { const amount = totalSupply; const parsedJettonMaster = Address.parse(jettonAddress!); const migrationMasterConfig: MigrationMasterConfig = { @@ -167,7 +166,7 @@ export function MigrationPopup({ const params = { code: MIGRATION_MASTER_CODE, data: await migrationMasterConfigToCell(migrationMasterConfig), - deployer: Address.parse(address!), + deployer: Address.parse(walletAddress!), value: MIGRATION_MASTER_DEPLOY_GAS, }; const migrationMasterAddress = new ContractDeployer().addressForContract(params); @@ -175,18 +174,17 @@ export function MigrationPopup({ const newMinterJettonWalletAddress = await makeGetCall( Address.parse(newMinterAddress), "get_wallet_address", - [beginCell().storeAddress(Address.parse(address!)).endCell()], + [beginCell().storeAddress(Address.parse(walletAddress!)).endCell()], ([addressCell]) => cellToAddress(addressCell), await getClient(), ); try { - const connection = WalletConnection.getConnection(); await jettonDeployController.transfer( connection, amount!, migrationMasterAddress.toFriendly(), - address!, + walletAddress!, newMinterJettonWalletAddress.toFriendly(), ); } catch (error) { diff --git a/src/pages/jetton/userMigration.tsx b/src/pages/jetton/userMigration.tsx index 4fd41f3..a43d0db 100644 --- a/src/pages/jetton/userMigration.tsx +++ b/src/pages/jetton/userMigration.tsx @@ -9,8 +9,7 @@ import CircularProgress from "@mui/material/CircularProgress"; import CheckCircleIcon from "@mui/icons-material/CheckCircle"; import { useNavigate } from "react-router-dom"; import WalletConnection from "services/wallet-connection"; -import useConnectionStore from "store/connection-store/useConnectionStore"; -import { TonConnection } from "@ton-defi.org/ton-connection"; +import { useTonAddress, useTonConnectUI, TonConnectUI } from "@tonconnect/ui-react"; import { Address, Cell, beginCell } from "ton"; import { JettonDeployParams, jettonDeployController } from "lib/deploy-controller"; import { createDeployParams, sleep } from "lib/utils"; @@ -74,9 +73,10 @@ export function UserMigrationPopup({ setMigrationHelperBalance, setTransferredJettonsToHelper, } = useJettonStore(); - const { address } = useConnectionStore(); const { showNotification } = useNotification(); const { jettonAddress } = useJettonAddress(); + const [tonconnect] = useTonConnectUI(); + const address = useTonAddress(); const navigate = useNavigate(); @@ -85,7 +85,7 @@ export function UserMigrationPopup({ }; const onSubmit = async () => { - const connection = WalletConnection.getConnection(); + const connection = tonconnect; if (!address || !connection) { throw new Error("Wallet not connected"); } @@ -94,7 +94,7 @@ export function UserMigrationPopup({ await transferJettonsToHelper(connection); }; - const deployMigrationHelper = async (connection: TonConnection) => { + const deployMigrationHelper = async (connection: TonConnectUI) => { if (!address || !connection) { throw new Error("Wallet not connected"); } @@ -145,12 +145,11 @@ export function UserMigrationPopup({ } }; - const transferJettonsToHelper = async (connection: TonConnection) => { + const transferJettonsToHelper = async (connection: TonConnectUI) => { const amount = balance!; const parsedJettonWallet = Address.parse(jettonWalletAddress!); try { - const connection = WalletConnection.getConnection(); await jettonDeployController.transfer( connection, amount!, diff --git a/src/store/jetton-store/useJettonStore.ts b/src/store/jetton-store/useJettonStore.ts index 7b1d015..b9648ae 100644 --- a/src/store/jetton-store/useJettonStore.ts +++ b/src/store/jetton-store/useJettonStore.ts @@ -1,13 +1,8 @@ -import { TonConnection, ChromeExtensionWalletProvider } from "@ton-defi.org/ton-connection"; import { JettonDeployParams, jettonDeployController } from "lib/deploy-controller"; import { createDeployParams, zeroAddress } from "lib/utils"; import { useRecoilState, useResetRecoilState } from "recoil"; import WalletConnection from "services/wallet-connection"; import { Address, Cell } from "ton"; -import { jettonDeployController } from "lib/deploy-controller"; -import { zeroAddress } from "lib/utils"; -import { useRecoilState, useResetRecoilState } from "recoil"; -import { Address } from "ton"; import { jettonStateAtom } from "."; import QuestiomMarkImg from "assets/icons/question.png"; import { useCallback } from "react"; @@ -247,7 +242,6 @@ function useJettonStore() { const result = await jettonDeployController.getJettonDetails( newMinterAddress, migrationMasterAddress, - connection, ); if (result) { From e8cf5dba8706c7a74246e6078d292439d2317e8d Mon Sep 17 00:00:00 2001 From: Daniil Sedov <42098239+Gusarich@users.noreply.github.com> Date: Thu, 6 Jul 2023 07:46:57 +0000 Subject: [PATCH 29/30] proper work with rejects --- src/pages/jetton/migration.tsx | 15 +++++++++------ src/pages/jetton/userMigration.tsx | 10 ++++++---- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/src/pages/jetton/migration.tsx b/src/pages/jetton/migration.tsx index 0174004..34f4276 100644 --- a/src/pages/jetton/migration.tsx +++ b/src/pages/jetton/migration.tsx @@ -106,12 +106,13 @@ export function MigrationPopup({ try { const result = await jettonDeployController.createJetton(params, connection, walletAddress); + setNewMinterDeployed(true); } catch (err) { if (err instanceof Error) { showNotification(<>{err.message}, "error"); + onClose(); + setMigrationStarted(false); } - } finally { - setNewMinterDeployed(true); } }; @@ -147,12 +148,13 @@ export function MigrationPopup({ connection, Address.parse(walletAddress), ); + setMigrationMasterDeployed(true); } catch (err) { if (err instanceof Error) { showNotification(<>{err.message}, "error"); + onClose(); + setMigrationStarted(false); } - } finally { - setMigrationMasterDeployed(true); } }; @@ -187,12 +189,13 @@ export function MigrationPopup({ walletAddress!, newMinterJettonWalletAddress.toFriendly(), ); + setMintedJettonsToMaster(true); } catch (error) { if (error instanceof Error) { showNotification(error.message, "error"); + onClose(); + setMigrationStarted(false); } - } finally { - setMintedJettonsToMaster(true); } }; diff --git a/src/pages/jetton/userMigration.tsx b/src/pages/jetton/userMigration.tsx index a43d0db..8c7a54f 100644 --- a/src/pages/jetton/userMigration.tsx +++ b/src/pages/jetton/userMigration.tsx @@ -136,12 +136,13 @@ export function UserMigrationPopup({ connection, Address.parse(address), ); + setMigrationHelperDeployed(true); } catch (err) { if (err instanceof Error) { showNotification(<>{err.message}, "error"); + onClose(); + setMigrationStarted(false); } - } finally { - setMigrationHelperDeployed(true); } }; @@ -159,12 +160,13 @@ export function UserMigrationPopup({ 0.35, 0.3, ); + setTransferredJettonsToHelper(true); } catch (error) { if (error instanceof Error) { showNotification(error.message, "error"); + onClose(); + setMigrationStarted(false); } - } finally { - setTransferredJettonsToHelper(true); } }; From 2d7abdcbdb6ace8c35db1d5057af30434b1b5eac Mon Sep 17 00:00:00 2001 From: Daniil Sedov <42098239+Gusarich@users.noreply.github.com> Date: Thu, 6 Jul 2023 07:48:15 +0000 Subject: [PATCH 30/30] remove console logs --- src/lib/contract-deployer.ts | 1 - src/lib/migrations.ts | 3 --- src/pages/jetton/userMigration.tsx | 10 +--------- 3 files changed, 1 insertion(+), 13 deletions(-) diff --git a/src/lib/contract-deployer.ts b/src/lib/contract-deployer.ts index 35ddf9b..bd8e7f9 100644 --- a/src/lib/contract-deployer.ts +++ b/src/lib/contract-deployer.ts @@ -13,7 +13,6 @@ interface ContractDeployDetails { export class ContractDeployer { addressForContract(params: ContractDeployDetails) { - console.log(77, params.data, params.code); return contractAddress({ workchain: 0, initialData: params.data, diff --git a/src/lib/migrations.ts b/src/lib/migrations.ts index 9f61e13..57be47d 100644 --- a/src/lib/migrations.ts +++ b/src/lib/migrations.ts @@ -132,12 +132,9 @@ export async function createMigrationHelper( if (await tc.isContractDeployed(migrationHelperAddress)) { // params.onProgress?.(JettonDeployState.ALREADY_DEPLOYED); } else { - console.log(123); await contractDeployer.deployContract(params, tonConnection); - console.log(123); // params.onProgress?.(JettonDeployState.AWAITING_MINTER_DEPLOY); await waitForContractDeploy(migrationHelperAddress, tc); - console.log(123); } return migrationHelperAddress; diff --git a/src/pages/jetton/userMigration.tsx b/src/pages/jetton/userMigration.tsx index 8c7a54f..3f2c2a7 100644 --- a/src/pages/jetton/userMigration.tsx +++ b/src/pages/jetton/userMigration.tsx @@ -99,31 +99,23 @@ export function UserMigrationPopup({ throw new Error("Wallet not connected"); } - console.log(jettonAddress!, migrationMaster); - const parsedJettonMaster = Address.parse(jettonAddress!); - console.log(123); - const migrationHelperConfig: MigrationHelperConfig = { oldJettonMinter: parsedJettonMaster, migrationMaster: Address.parse(migrationMaster), recipient: Address.parse(address), }; - console.log(123, address, MIGRATION_HELPER_CODE); const params = { code: MIGRATION_HELPER_CODE, data: await migrationHelperConfigToCell(migrationHelperConfig), deployer: Address.parse(address), value: MIGRATION_HELPER_DEPLOY_GAS, }; - console.log(123); const migrationHelperAddress = new ContractDeployer().addressForContract(params); - console.log(123); + const client = await getClient(); - console.log(123); const isDeployed = await client.isContractDeployed(migrationHelperAddress); - console.log(123); if (isDeployed) { setMigrationHelperDeployed(true);