From fe1a445c5370ff195700ae4b7d16e8ffed0842fe Mon Sep 17 00:00:00 2001 From: Sophie Date: Mon, 18 Mar 2024 17:06:18 -0700 Subject: [PATCH] src20 example --- app/src/constants.ts | 140 ++++++++++++++++-- .../editor/components/ExampleDropdown.tsx | 80 +++++----- projects/swaypad/Forc.lock | 26 +++- projects/swaypad/Forc.toml | 3 + 4 files changed, 191 insertions(+), 58 deletions(-) diff --git a/app/src/constants.ts b/app/src/constants.ts index c6907bc..0b77aea 100644 --- a/app/src/constants.ts +++ b/app/src/constants.ts @@ -36,31 +36,141 @@ impl Counter for Contract { }`; // TODO -export const EXAMPLE_SWAY_CONTRACT_2 = `contract; +export const EXAMPLE_SWAY_CONTRACT_SRC20 = `contract; + +use src3::SRC3; +use src5::{SRC5, State, AccessError}; +use src20::SRC20; +use std::{ + asset::{ + burn, + mint_to, + }, + call_frames::{ + contract_id, + msg_asset_id, + }, + constants::DEFAULT_SUB_ID, + context::msg_amount, + string::String, +}; -abi Counter { +abi Constructor { #[storage(read, write)] - fn increment(amount: u64) -> u64; + fn constructor(owner_: Identity); +} - #[storage(read)] - fn get() -> u64; +configurable { + /// The decimals of the asset minted by this contract. + DECIMALS: u8 = 9u8, + /// The name of the asset minted by this contract. + NAME: str[7] = __to_str_array("MyAsset"), + /// The symbol of the asset minted by this contract. + SYMBOL: str[5] = __to_str_array("MYTKN"), } storage { - counter: u64 = 0, + /// The total supply of the asset minted by this contract. + total_supply: u64 = 0, + + /// Owner. + owner: State = State::Uninitialized, } -impl Counter for Contract { +impl SRC20 for Contract { + #[storage(read)] + fn total_assets() -> u64 { + 1 + } + + #[storage(read)] + fn total_supply(asset: AssetId) -> Option { + if asset == AssetId::default() { + Some(storage.total_supply.read()) + } else { + None + } + } + + #[storage(read)] + fn name(asset: AssetId) -> Option { + if asset == AssetId::default() { + Some(String::from_ascii_str(from_str_array(NAME))) + } else { + None + } + } + + #[storage(read)] + fn symbol(asset: AssetId) -> Option { + if asset == AssetId::default() { + Some(String::from_ascii_str(from_str_array(SYMBOL))) + } else { + None + } + } + + #[storage(read)] + fn decimals(asset: AssetId) -> Option { + if asset == AssetId::default() { + Some(DECIMALS) + } else { + None + } + } +} + +#[storage(read)] +fn is_owner() { + require( + storage.owner.read() == State::Initialized(msg_sender().unwrap()), + AccessError::NotOwner, + ); +} + +impl Constructor for Contract { #[storage(read, write)] - fn increment(amount: u64) -> u64 { - let incremented = storage.counter.read() + amount; - storage.counter.write(incremented); - incremented + fn constructor(owner_: Identity) { + require(storage.owner.read() == State::Uninitialized, "owner-initialized"); + storage.owner.write(State::Initialized(owner_)); } +} +impl SRC5 for Contract { #[storage(read)] - fn get() -> u64 { - storage.counter.read() + fn owner() -> State { + storage.owner.read() + } +} + +impl SRC3 for Contract { + #[storage(read, write)] + fn mint(recipient: Identity, sub_id: SubId, amount: u64) { + require(sub_id == DEFAULT_SUB_ID, "Incorrect Sub Id"); + is_owner(); + + // Increment total supply of the asset and mint to the recipient. + storage + .total_supply + .write(amount + storage.total_supply.read()); + mint_to(recipient, DEFAULT_SUB_ID, amount); + } + + #[storage(read, write)] + fn burn(sub_id: SubId, amount: u64) { + require(sub_id == DEFAULT_SUB_ID, "Incorrect Sub Id"); + require(msg_amount() >= amount, "Incorrect amount provided"); + require( + msg_asset_id() == AssetId::default(), + "Incorrect asset provided", + ); + is_owner(); + + // Decrement total supply of the asset and burn. + storage + .total_supply + .write(storage.total_supply.read() - amount); + burn(DEFAULT_SUB_ID, amount); } }`; @@ -236,8 +346,8 @@ contract Voting { }`; export const EXAMPLE_SWAY_CONTRACTS: ExampleMenuItem[] = [ - { label: 'counter.sw', code: EXAMPLE_SWAY_CONTRACT_COUNTER }, - { label: 'Example 2', code: EXAMPLE_SWAY_CONTRACT_2 }, + { label: 'Counter.sw', code: EXAMPLE_SWAY_CONTRACT_COUNTER }, + { label: 'SRC20.sw', code: EXAMPLE_SWAY_CONTRACT_SRC20 }, { label: 'Example 3', code: EXAMPLE_SWAY_CONTRACT_3 }, ]; diff --git a/app/src/features/editor/components/ExampleDropdown.tsx b/app/src/features/editor/components/ExampleDropdown.tsx index 0d3766e..2f22e6d 100644 --- a/app/src/features/editor/components/ExampleDropdown.tsx +++ b/app/src/features/editor/components/ExampleDropdown.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { useCallback } from 'react'; import Tooltip from '@mui/material/Tooltip'; import MenuItem from '@mui/material/MenuItem'; import IconButton from '@mui/material/IconButton'; @@ -17,56 +17,56 @@ export interface ExampleDropdownProps { style?: React.CSSProperties; } -function ExampleDropdown({ handleSelect, examples, style }: ExampleDropdownProps) { +function ExampleDropdown({ + handleSelect, + examples, + style, +}: ExampleDropdownProps) { const [anchorEl, setAnchorEl] = React.useState(null); - const onButtonClick = (event: any ) => { // todo - console.log('click', event.target); + const onButtonClick = useCallback((event: any) => { setAnchorEl(event.target); - }; + }, [setAnchorEl]); - const onItemClick = (code: string) => { // todo - console.log(code); - // console.log('item click', event.target.value); + const handleClose = useCallback(() => { + setAnchorEl(null); + }, [setAnchorEl]); + + const onItemClick = useCallback((code: string) => { handleClose(); - // handleSelect(event.target.value); handleSelect(code); - }; - - - const handleClose = () => { - console.log('close'); - setAnchorEl(null); - } + }, [handleSelect, handleClose]); return (
- - - - - - - - + + + + + - - {examples.map(({label, code}: ExampleMenuItem, index) => ( onItemClick(code)} >{label})) } - {/* Profile - Language settings - Log out */} - - + + {examples.map(({ label, code }: ExampleMenuItem, index) => ( + onItemClick(code)}> + {label} + + ))} + +
); } diff --git a/projects/swaypad/Forc.lock b/projects/swaypad/Forc.lock index 970f608..97e0647 100644 --- a/projects/swaypad/Forc.lock +++ b/projects/swaypad/Forc.lock @@ -1,13 +1,33 @@ [[package]] name = "core" -source = "path+from-root-63B5D95B29B128A3" +source = "path+from-root-4F1FAAE4510FEB23" + +[[package]] +name = "src20" +source = "git+https://github.com/FuelLabs/sway-standards?tag=v0.3.3#4198b4b07449ad16104cc8a0501f3013670fdcfd" +dependencies = ["std"] + +[[package]] +name = "src3" +source = "git+https://github.com/FuelLabs/sway-standards?tag=v0.3.3#4198b4b07449ad16104cc8a0501f3013670fdcfd" +dependencies = ["std"] + +[[package]] +name = "src5" +source = "git+https://github.com/FuelLabs/sway-standards?tag=v0.3.3#4198b4b07449ad16104cc8a0501f3013670fdcfd" +dependencies = ["std"] [[package]] name = "std" -source = "git+https://github.com/fuellabs/sway?tag=v0.45.0#92dc9f361a9508a940c0d0708130f26fa044f6b3" +source = "git+https://github.com/fuellabs/sway?tag=v0.51.1#d1e8f019c1da46273c3d3a72b385ce356ba2bc20" dependencies = ["core"] [[package]] name = "swaypad" source = "member" -dependencies = ["std"] +dependencies = [ + "src20", + "src3", + "src5", + "std", +] diff --git a/projects/swaypad/Forc.toml b/projects/swaypad/Forc.toml index bf41688..0c20011 100644 --- a/projects/swaypad/Forc.toml +++ b/projects/swaypad/Forc.toml @@ -5,3 +5,6 @@ license = "Apache-2.0" name = "swaypad" [dependencies] +src3 = { git = "https://github.com/FuelLabs/sway-standards", tag = "v0.3.3" } +src5 = { git = "https://github.com/FuelLabs/sway-standards", tag = "v0.3.3" } +src20 = { git = "https://github.com/FuelLabs/sway-standards", tag = "v0.3.3" }