Skip to content

Commit

Permalink
Merge pull request #2243 from dusk-network/feature-2014
Browse files Browse the repository at this point in the history
web-wallet: add token migration contract bindings
  • Loading branch information
deuch13 authored Sep 4, 2024
2 parents 19ec993 + ee5718c commit 15d03c8
Show file tree
Hide file tree
Showing 26 changed files with 1,247 additions and 264 deletions.
3 changes: 3 additions & 0 deletions web-wallet/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

- Added gas settings validation on Unstake / Widthdraw Rewards flows [#2000]
- Added allocation (shield/unshield) page and UI [#2196]
- Added token migration contract bindings [#2014]

### Changed

Expand Down Expand Up @@ -242,6 +243,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
[#2071]: https://github.com/dusk-network/rusk/issues/2075
[#2118]: https://github.com/dusk-network/rusk/issues/2118
[#2118]: https://github.com/dusk-network/rusk/issues/2175
[#2196]: https://github.com/dusk-network/rusk/issues/2196
[#2014]: https://github.com/dusk-network/rusk/issues/2014

<!-- VERSIONS -->

Expand Down
2 changes: 2 additions & 0 deletions web-wallet/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ N.B. the current `0.1.2` version of the library has no option to pick the networ
# can be empty string, must start with a slash otherwise, must not end with a slash
VITE_BASE_PATH=""
VITE_CONTRACT_ALLOCATE_DISABLED=true
VITE_CONTRACT_MIGRATE_DISABLED=true
VITE_CONTRACT_STAKE_DISABLED=false
VITE_CONTRACT_TRANSFER_DISABLED=false
VITE_CURRENT_NODE=${VITE_LOCAL_NODE}
Expand All @@ -45,6 +46,7 @@ VITE_GAS_PRICE_DEFAULT=1
VITE_GAS_PRICE_LOWER=1
VITE_LOCAL_NODE="https://localhost:5173/rusk/"
VITE_MAINNET_NODE=""
VITE_MIGRATE_CONTRACT=""
VITE_MINIMUM_ALLOWED_STAKE=1000
VITE_RKYV_TREE_LEAF_SIZE=632
VITE_STAKE_CONTRACT="0200000000000000000000000000000000000000000000000000000000000000"
Expand Down
142 changes: 142 additions & 0 deletions web-wallet/src/lib/components/ApproveMigration/ApproveMigration.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
<svelte:options immutable={true} />

<script>
import { mdiAlertOutline, mdiTimerSand } from "@mdi/js";
import { waitForTransactionReceipt } from "@wagmi/core";
import { isHex } from "viem";
import { createEventDispatcher } from "svelte";
import { Button, Icon } from "$lib/dusk/components";
import { account, wagmiConfig } from "$lib/migration/walletConnection";
import { allowance, approve } from "$lib/migration/migration";
import { createDataStore } from "$lib/dusk/svelte-stores";
/** @type {number} */
export let amount;
/** @type {HexString} */
export let chainContract;
/** @type {HexString} */
export let migrationContract;
$: ({ address } = $account);
let hasApprovedCoin = false;
const dispatch = createEventDispatcher();
const approvalTxStore = createDataStore(handleApprove);
$: ({ isLoading, data, error } = $approvalTxStore);
async function checkAllowance() {
if (!address) {
dispatch("errorApproval");
throw new Error("Address is undefined");
}
try {
const allowedAmount = await allowance(
address,
chainContract,
migrationContract
);
return Number(allowedAmount) >= amount;
} catch (e) {
return false;
}
}
async function handleApprove() {
dispatch("initApproval");
hasApprovedCoin = await checkAllowance();
if (!hasApprovedCoin) {
const txHash = await approve(
migrationContract,
chainContract,
amount.toString()
);
if (isHex(txHash)) {
dispatch("incrementStep");
await waitForTransactionReceipt(wagmiConfig, {
confirmations: 3,
hash: txHash,
});
hasApprovedCoin = await checkAllowance();
} else {
dispatch("errorApproval");
throw new Error("txHash is not a hex string");
}
} else {
dispatch("incrementStep");
}
}
</script>

<div class="migrate__approve">
{#if !isLoading && !error && !data}
<div class="migrate__approve-notice">
<p>DUSK token migration requires two transactions:</p>
<ol class="migrate__approve-notice-list">
<li>
Approve: Authorize the migration contract to spend your DUSK tokens.
</li>
<li>Migrate: Transfer your DUSK tokens to the migration contract.</li>
</ol>
<p>
Both steps must be completed for a successful migration.<br /><br
/>Warning: Make sure your wallet has enough funds to pay for the gas.
</p>
</div>
{:else if isLoading}
<div class="migrate__approve-approval">
<Icon path={mdiTimerSand} />
<span>Approval in progress</span>
</div>
{:else if error}
<div class="migrate__approve-approval">
<Icon path={mdiAlertOutline} />
<span>An error occured during approval</span>
</div>
{/if}

<Button
text={error ? "RETRY APPROVAL" : "APPROVE MIGRATION"}
disabled={!!isLoading}
on:click={approvalTxStore.getData}
/>
</div>

<style lang="postcss">
.migrate__approve {
display: flex;
justify-content: center;
flex-direction: column;
&-notice {
font-size: 0.875em;
line-height: 1.3125em;
padding: 1em 1.375em;
border-radius: 0.675em;
border: 1px solid var(--primary-color);
margin-top: 0.625em;
margin-bottom: 1em;
&-list {
padding-left: 1.375em;
}
}
&-approval {
display: flex;
flex-direction: column;
align-items: center;
gap: var(--default-gap);
padding: 2.25em 0;
}
}
</style>
121 changes: 121 additions & 0 deletions web-wallet/src/lib/components/ExecuteMigration/ExecuteMigration.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
<svelte:options immutable={true} />

<script>
import {
mdiAlertOutline,
mdiCheckDecagramOutline,
mdiTimerSand,
} from "@mdi/js";
import { waitForTransactionReceipt } from "@wagmi/core";
import { isHex } from "viem";
import { AppAnchor } from "$lib/components";
import { Button, Icon } from "$lib/dusk/components";
import { account, wagmiConfig } from "$lib/migration/walletConnection";
import { migrate } from "$lib/migration/migration";
import { createDataStore } from "$lib/dusk/svelte-stores";
/** @type {number} */
export let amount;
/** @type {string} */
export let currentAddress;
/** @type {HexString} */
export let migrationContract;
/** @type {string} */
let migrationHash = "";
const migrationStore = createDataStore(handleMigration);
$: ({ chain, chainId } = $account);
$: ({ data, error, isLoading } = $migrationStore);
/** @param {number} id - the chain id of the selected smart contract */
async function handleMigration(id) {
const txHash = await migrate(
amount.toString(),
id,
currentAddress,
migrationContract
);
if (isHex(txHash)) {
migrationHash = txHash;
return waitForTransactionReceipt(wagmiConfig, {
confirmations: 10,
hash: txHash,
});
} else {
throw new Error("txHash is not a hex string");
}
}
</script>

<div class="migrate__execute">
{#if !isLoading && !data && !error}
<div class="migrate__execute-approval">
<Icon path={mdiCheckDecagramOutline} />
<span>Migration Approved</span>
</div>
{:else if error}
<div class="migrate__execute-approval">
<Icon path={mdiAlertOutline} />
<span>Action has been rejected on the connected wallet.</span>
</div>
{:else if isLoading && !migrationHash}
<div class="migrate__execute-approval">
<Icon path={mdiTimerSand} />
<span>Migration in progress</span>
</div>
{/if}
{#if migrationHash && chain?.blockExplorers}
<div class="migrate__execute-approval">
<Icon path={mdiCheckDecagramOutline} />
<span>Migration has been submitted</span>
</div>
<div class="migrate__execute-notice">
<span
>Migration takes some minutes to complete. Your transaction is being
executed and you can check it <AppAnchor
href={`${chain.blockExplorers.default.url}/tx/${migrationHash}`}
target="_blank"
rel="noopener noreferrer">here</AppAnchor
>.</span
>
</div>
{/if}
{#if (isLoading || !data || error) && !migrationHash}
<Button
text={`${error ? "RETRY" : "EXECUTE"} MIGRATION`}
disabled={!!isLoading}
on:click={() => migrationStore.getData(chainId)}
/>
{/if}
</div>

<style lang="postcss">
.migrate__execute {
display: flex;
justify-content: center;
flex-direction: column;
&-notice {
font-size: 0.875em;
line-height: 1.3125em;
padding: 1em 1.375em;
border-radius: 0.675em;
border: 1px solid var(--primary-color);
margin-top: 0.625em;
margin-bottom: 1em;
}
&-approval {
display: flex;
flex-direction: column;
align-items: center;
gap: var(--default-gap);
padding: 2.25em 0;
}
}
</style>
2 changes: 2 additions & 0 deletions web-wallet/src/lib/components/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@ export { default as Allocate } from "./Allocate/Allocate.svelte";
export { default as AppAnchor } from "./AppAnchor/AppAnchor.svelte";
export { default as AppAnchorButton } from "./AppAnchorButton/AppAnchorButton.svelte";
export { default as AppImage } from "./AppImage/AppImage.svelte";
export { default as ApproveMigration } from "./ApproveMigration/ApproveMigration.svelte";
export { default as Balance } from "./Balance/Balance.svelte";
export { default as ContractOperations } from "./ContractOperations/ContractOperations.svelte";
export { default as ContractStatusesList } from "./ContractStatusesList/ContractStatusesList.svelte";
export { default as DashboardNav } from "./DashboardNav/DashboardNav.svelte";
export { default as ExecuteMigration } from "./ExecuteMigration/ExecuteMigration.svelte";
export { default as ExistingWalletNotice } from "./ExistingWalletNotice/ExistingWalletNotice.svelte";
export { default as GasControls } from "./GasControls/GasControls.svelte";
export { default as GasFee } from "./GasFee/GasFee.svelte";
Expand Down
Loading

0 comments on commit 15d03c8

Please sign in to comment.