From cf02f60f75879fae0e8f8f61ae8003bf0e965979 Mon Sep 17 00:00:00 2001 From: Chad Ostrowski <221614+chadoh@users.noreply.github.com> Date: Thu, 6 Jul 2023 11:09:36 -0700 Subject: [PATCH] feat: switch from soroban-react to generated libs (#117) * feat: switch from soroban-react to generated libs * feat: add ft-contract source; rm `../examples` - don't use `soroban lab token` to generate/deploy token - instead, copy example token from examples repo - remove `../examples` reference in `generate` script - add `target/bin/soroban` with pinned version of `soroban` to be used throughout initialize.sh * fix: use workspace dependency versions; update sdk * feat: no more embedding secret keys This copies ideas from the contract in https://github.com/AhaLabs/soroban-abundance-token, allowing anyone to mint themselves tokens. Now this can be used from the frontend directly, so we no longer need to embed the admin's secret key in the JS. Hooray! Upon closer inspection, we didn't need any of those constants anymore, since the contract IDs are embedded in the token libraries. * fix: add mint_100 and comment out events * fix: start tryna fix event subscriptions * fix: update UI after minting 100 ABND * fix: signAndSend `deposit`; fix modal; update form The whole page no longer reloads after a pledge. Instead, FormPledge now takes an `onPledge` param, which it calls after the pledge succeeds. The now-somewhat-awkward `resultSubmit` has also been filled back out to match what the modal expects, so the modal looks correct. * docs: update AlmostUnnecessaryProvider comment * build: allow newer node versions; improve package name * build: generate contract clients * build: fill in .soroban-example-dapp/* first The CI script needs the values there before it can generate the libraries, of course. And the `token_admin*` stuff isn't needed anymore. * build: install locked CLI version with alias * build: build contracts before generating clients * build: s/run-script/run/ Replace `run-script` with the much more common alias `run` to match the rest of the workflow file * build: make convert.ts pass strict; exclude target/ from type checking * build: use node 18 in CI * build: update lockfile; cat lockfiles during build * build: switch to yarn; will it work better? * build: omg yarn works with relative paths but not file: * build: rm busted debug steps; update docs for yarn * build: s/yarn ci/yarn install --frozen-lockfile * build: back to npm we go * build: switch to postinstall script * build: rm outdated build step * build: warn, don't deny, on clippy complaints and add .cargo/config.toml to match CI settings * feat: use freighter-api@1.5 * feat: straightforward copy/paste of subscribe logic This gets the subscriptions working, and finally breaks all dependence on the @soroban-react packages. The logic is a little confusing, but it works! * feat: move subscribe logic to useSubscription hook This is a hook that can be copy/pasted into other React projects that need such functionality, to work alongside their generated libraries until these generated libraries expose subscription logic natively. * fix: update all relevant UI after pledging * fix: avoid Freighter error if not yet connected * fix: can't default build to wasm because tests * build: use latest soroban-cli Uses the version with updated freighter-api https://github.com/stellar/soroban-tools/pull/708 * build: use latest cli/soroban-client; rm stellar-base pin * build: use latest CLI rev from stellar repo * fix: deal with undefined case * build: rm RUSTFLAGS from Makefile Since d771b3f28599664d3e96c313397bb6aad3b71d38, the default settings are now set in `.cargo/config.toml` * fix: allow using standalone Everything looks correct, but when running the app it fails with: Error: Cannot connect to insecure soroban-rpc server * build: update freighter-api * build: update pinned soroban-cli version * build(ci): stub .soroban-example-dapp/network * fix: add 'await' --------- Co-authored-by: Willem Wyndham --- .cargo/config.toml | 133 + .github/workflows/nodejs.yml | 19 +- .github/workflows/rust.yml | 2 +- Cargo.lock | 17 + Cargo.toml | 13 +- Dockerfile | 1 - Makefile | 1 - README.md | 21 +- components/ProviderExample.tsx | 22 - components/atoms/connect-button/index.tsx | 9 +- components/molecules/deposits/index.tsx | 28 +- components/molecules/form-pledge/index.tsx | 255 +- components/molecules/wallet-data/index.tsx | 26 +- components/organisms/pledge/index.tsx | 193 +- contracts/abundance/Cargo.toml | 15 + contracts/abundance/src/admin.rs | 17 + contracts/abundance/src/allowance.rs | 24 + contracts/abundance/src/balance.rs | 49 + contracts/abundance/src/contract.rs | 206 + contracts/abundance/src/event.rs | 41 + contracts/abundance/src/lib.rs | 12 + contracts/abundance/src/metadata.rs | 22 + contracts/abundance/src/storage_types.rs | 18 + contracts/abundance/src/test.rs | 273 ++ convert.ts | 263 +- hooks/index.ts | 3 + hooks/index.tsx | 2 - hooks/useAccount.ts | 49 + hooks/useAccount.tsx | 15 - hooks/{useIsMounted.tsx => useIsMounted.ts} | 0 hooks/useSubscription.ts | 101 + initialize.sh | 116 +- next.config.js | 7 - package-lock.json | 4221 +------------------ package.json | 33 +- pages/_app.tsx | 8 +- shared/constants.tsx | 19 - shared/utils.tsx | 34 +- tsconfig.json | 5 +- 39 files changed, 1555 insertions(+), 4738 deletions(-) create mode 100644 .cargo/config.toml delete mode 100644 components/ProviderExample.tsx create mode 100644 contracts/abundance/Cargo.toml create mode 100644 contracts/abundance/src/admin.rs create mode 100644 contracts/abundance/src/allowance.rs create mode 100644 contracts/abundance/src/balance.rs create mode 100644 contracts/abundance/src/contract.rs create mode 100644 contracts/abundance/src/event.rs create mode 100644 contracts/abundance/src/lib.rs create mode 100644 contracts/abundance/src/metadata.rs create mode 100644 contracts/abundance/src/storage_types.rs create mode 100644 contracts/abundance/src/test.rs create mode 100644 hooks/index.ts delete mode 100644 hooks/index.tsx create mode 100644 hooks/useAccount.ts delete mode 100644 hooks/useAccount.tsx rename hooks/{useIsMounted.tsx => useIsMounted.ts} (100%) create mode 100644 hooks/useSubscription.ts delete mode 100644 shared/constants.tsx diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 0000000..81cb1ef --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,133 @@ +# paths = ["/path/to/override"] # path dependency overrides + +[alias] # command aliases +install_soroban = "install --git https://github.com/stellar/soroban-tools --rev 2b343d3e6afdb5eff54fb03622627cd55e785358 --root ./target soroban-cli --debug" +b = "build --target wasm32-unknown-unknown --release" +# c = "check" +# t = "test" +# r = "run" +# rr = "run --release" +# recursive_example = "rr --example recursions" +# space_example = ["run", "--release", "--", "\"command list\""] + +[build] +# jobs = 1 # number of parallel jobs, defaults to # of CPUs +# rustc = "rustc" # the rust compiler tool +# rustc-wrapper = "…" # run this wrapper instead of `rustc` +# rustc-workspace-wrapper = "…" # run this wrapper instead of `rustc` for workspace members +# rustdoc = "rustdoc" # the doc generator tool +# target = "wasm32-unknown-unknown" # build for the target triple (ignored by `cargo install`) +# target-dir = "target" # path of where to place all generated artifacts +rustflags = [ # set these to match .github/workflows/rust.yml + "-Wclippy::all", # warn for all clippy lints + "-Wclippy::pedantic", # warn for pedantic clippy lints +] # custom flags to pass to all compiler invocations +# rustdocflags = ["…", "…"] # custom flags to pass to rustdoc +# incremental = true # whether or not to enable incremental compilation +# dep-info-basedir = "…" # path for the base directory for targets in depfiles + +# [doc] +# browser = "chromium" # browser to use with `cargo doc --open`, +# # overrides the `BROWSER` environment variable + +# [env] +# # Set ENV_VAR_NAME=value for any process run by Cargo +# ENV_VAR_NAME = "value" +# # Set even if already present in environment +# ENV_VAR_NAME_2 = { value = "value", force = true } +# # Value is relative to .cargo directory containing `config.toml`, make absolute +# ENV_VAR_NAME_3 = { value = "relative/path", relative = true } + +# [future-incompat-report] +# frequency = 'always' # when to display a notification about a future incompat report + +# [cargo-new] +# vcs = "none" # VCS to use ('git', 'hg', 'pijul', 'fossil', 'none') + +# [http] +# debug = false # HTTP debugging +# proxy = "host:port" # HTTP proxy in libcurl format +# ssl-version = "tlsv1.3" # TLS version to use +# ssl-version.max = "tlsv1.3" # maximum TLS version +# ssl-version.min = "tlsv1.1" # minimum TLS version +# timeout = 30 # timeout for each HTTP request, in seconds +# low-speed-limit = 10 # network timeout threshold (bytes/sec) +# cainfo = "cert.pem" # path to Certificate Authority (CA) bundle +# check-revoke = true # check for SSL certificate revocation +# multiplexing = true # HTTP/2 multiplexing +# user-agent = "…" # the user-agent header + +# [install] +# root = "/some/path" # `cargo install` destination directory + +# [net] +# retry = 2 # network retries +# git-fetch-with-cli = true # use the `git` executable for git operations +# offline = true # do not access the network + +# [net.ssh] +# known-hosts = ["..."] # known SSH host keys + +# [patch.] +# # Same keys as for [patch] in Cargo.toml + +# [profile.] # Modify profile settings via config. +# inherits = "dev" # Inherits settings from [profile.dev]. +# opt-level = 0 # Optimization level. +# debug = true # Include debug info. +# split-debuginfo = '...' # Debug info splitting behavior. +# debug-assertions = true # Enables debug assertions. +# overflow-checks = true # Enables runtime integer overflow checks. +# lto = false # Sets link-time optimization. +# panic = 'unwind' # The panic strategy. +# incremental = true # Incremental compilation. +# codegen-units = 16 # Number of code generation units. +# rpath = false # Sets the rpath linking option. +# [profile..build-override] # Overrides build-script settings. +# # Same keys for a normal profile. +# [profile..package.] # Override profile for a package. +# # Same keys for a normal profile (minus `panic`, `lto`, and `rpath`). + +# [registries.] # registries other than crates.io +# index = "…" # URL of the registry index +# token = "…" # authentication token for the registry + +# [registry] +# default = "…" # name of the default registry +# token = "…" # authentication token for crates.io + +# [source.] # source definition and replacement +# replace-with = "…" # replace this source with the given named source +# directory = "…" # path to a directory source +# registry = "…" # URL to a registry source +# local-registry = "…" # path to a local registry source +# git = "…" # URL of a git repository source +# branch = "…" # branch name for the git repository +# tag = "…" # tag name for the git repository +# rev = "…" # revision for the git repository + +# [target.] +# linker = "…" # linker to use +# runner = "…" # wrapper to run executables +# rustflags = ["…", "…"] # custom flags for `rustc` + +# [target.] +# runner = "…" # wrapper to run executables +# rustflags = ["…", "…"] # custom flags for `rustc` + +# [target..] # `links` build script override +# rustc-link-lib = ["foo"] +# rustc-link-search = ["/path/to/foo"] +# rustc-flags = ["-L", "/some/path"] +# rustc-cfg = ['key="value"'] +# rustc-env = {key = "value"} +# rustc-cdylib-link-arg = ["…"] +# metadata_key1 = "value" +# metadata_key2 = "value" + +# [term] +# quiet = false # whether cargo output is quiet +# verbose = false # whether cargo provides verbose output +# color = 'auto' # whether cargo colorizes output +# progress.when = 'auto' # whether cargo shows progress bar +# progress.width = 80 # width of progress bar diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml index bafaa5c..7a50611 100644 --- a/.github/workflows/nodejs.yml +++ b/.github/workflows/nodejs.yml @@ -22,17 +22,16 @@ jobs: - uses: stellar/actions/rust-cache@main - run: rustup update - run: rustup target add wasm32-unknown-unknown - - run: cargo install --target-dir ~/.cargo/target --locked --version 0.8.0 soroban-cli - - name: Use Node.js 17.x - uses: actions/setup-node@v3 + - run: make build + - run: cargo install_soroban + - uses: actions/setup-node@v3 with: - node-version: 17.x + node-version: 18.x cache: 'npm' - - run: npm ci - run: | mkdir -p .soroban-example-dapp - echo 'a9ab643486dc0dbcdc1485e6589e8bb3bcbbd8e69ad66c703556b4d6645a6dc8' > .soroban-example-dapp/token_id - echo '42798d5db884626e57f96630e7d02ba8210b4629d2959ef79ebb9e6538676ef9' > .soroban-example-dapp/crowdfund_id - echo 'GDT2NORMZF6S2T4PT4OBJJ43OPD3GPRNTJG3WVVFB356TUHWZQMU6C3U' > .soroban-example-dapp/token_admin_address - echo 'SAKCFFFNCE7XAWYMYVRZQYKUK6KMUCDIINLWISJYTMYJLNR2QLCDLFVT' > .soroban-example-dapp/token_admin_secret - - run: npm run-script build + echo 'futurenet' > .soroban-example-dapp/network + echo 'CC757WDV3G442WQCNPNOA2UEXOC7UJD5VP4BLLCRDW5LRM6UZZR6ISVU' > .soroban-example-dapp/abundance_token_id + echo 'CCHCPXECLYGX4QU34ZZOHP6C6KVAPIDTUNPIUA6GF4SP6ECFF5BX57OG' > .soroban-example-dapp/crowdfund_id + - run: npm ci + - run: npm run build diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index d563d9e..19de711 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -6,7 +6,7 @@ on: pull_request: env: - RUSTFLAGS: -Dwarnings -Dclippy::all -Dclippy::pedantic + RUSTFLAGS: -Wclippy::all -Wclippy::pedantic jobs: diff --git a/Cargo.lock b/Cargo.lock index d0f5180..876b350 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,14 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "abundance-token" +version = "0.0.6" +dependencies = [ + "soroban-sdk", + "soroban-token-sdk", +] + [[package]] name = "addr2line" version = "0.19.0" @@ -894,6 +902,15 @@ dependencies = [ "wasmparser", ] +[[package]] +name = "soroban-token-sdk" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49ae7d31ee22fc39b19d8b76bcf4e2b05b238839bcae871007c9d42d894ef512" +dependencies = [ + "soroban-sdk", +] + [[package]] name = "soroban-wasmi" version = "0.16.0-soroban2" diff --git a/Cargo.toml b/Cargo.toml index 9f3b8f5..1c6be9a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,7 @@ resolver = "2" members = [ - "contracts/crowdfund", + "contracts/*", ] [profile.release] @@ -15,11 +15,6 @@ panic = "abort" codegen-units = 1 lto = true -[workspace.dependencies.soroban-sdk] -version = "0.8.2" - - - - - - +[workspace.dependencies] +soroban-sdk = "0.8.4" +soroban-token-sdk = "0.8.4" diff --git a/Dockerfile b/Dockerfile index 46a0d6b..cadb8e4 100755 --- a/Dockerfile +++ b/Dockerfile @@ -12,7 +12,6 @@ ENV PATH="$PATH:/root/.cargo/bin" RUN rustup target add wasm32-unknown-unknown RUN apt install -y build-essential -RUN cargo install --locked --version 0.8.0 soroban-cli # WORKDIR / RUN mkdir /workspace WORKDIR /workspace diff --git a/Makefile b/Makefile index 96497c0..3919581 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,5 @@ all: check build test -export RUSTFLAGS=-Dwarnings -Dclippy::all -Dclippy::pedantic CARGO_BUILD_TARGET?=wasm32-unknown-unknown test: fmt diff --git a/README.md b/README.md index 71f3a11..41fd693 100755 --- a/README.md +++ b/README.md @@ -12,9 +12,9 @@ Getting Started Install Dependencies -------------------- -1. `soroban-cli v0.8.0`. See https://soroban.stellar.org/docs/getting-started/setup#install-the-soroban-cli +1. `soroban-cli`. See https://soroban.stellar.org/docs/getting-started/setup#install-the-soroban-cli, but instead of `cargo install soroban-cli`, run `cargo install_soroban`. This is an alias set up in [.cargo/config.toml](./.cargo/config.toml), which pins the local soroban-cli to a specific version. If you add `./target/bin/` [to your PATH](https://linuxize.com/post/how-to-add-directory-to-path-in-linux/), then you'll automatically use this version of `soroban-cli` when you're in this directory. 2. If you want to run everything locally: `docker` (you can run both Standalone and Futurenet backends with it) -3. `Node.js v17` +3. Node.js v18 4. [Freighter Wallet](https://www.freighter.app/) ≥[v5.0.2](https://github.com/stellar/freighter/releases/tag/2.9.1). Or from the Firefox / Chrome extension store. Once installed, enable "Experimental Mode" in the settings (gear icon). 5. If you want to run everything locally, build the `soroban-preview` docker image: @@ -33,9 +33,9 @@ You have three options: 1. Deploy on [Futurenet](https://soroban.stellar.org/doc 1. Deploy the contracts and initialize them - ./initialize.sh futurenet + npm run setup - This will create a `token-admin` identity for you (`soroban config identity create token-admin`) and deploy a Fungible Token contract as well as the [crowdfund contract](./contracts/crowdfund), with this account as admin. + This runs `./initialize.sh futurenet` behind the scenes, which will create a `token-admin` identity for you (`soroban config identity create token-admin`) and deploy a Fungible Token contract as well as the [crowdfund contract](./contracts/crowdfund), with this account as admin. 2. Select the Futurenet network in your Freighter browser extension @@ -91,7 +91,7 @@ You have three options: 1. Deploy on [Futurenet](https://soroban.stellar.org/doc You can use your own local soroban-cli: - ./initialize.sh standalone + NETWORK=standalone npm run setup Or run it inside the soroban-preview docker container: @@ -148,14 +148,3 @@ Then via the web UI, users should be able to: - Deposit an allowed asset - See their deposit(s) appear on the page as the transactions are confirmed. - "Live"-Update the page with the total amount with the new amount - -Wallet Integration & Data Fetching -================================== - -There is a `./wallet` directory, which contains a small library to connect to -the user's freighter wallet, as well as some React hooks to talk to a -soroban-rpc server (e.g. `soroban-cli serve`), to fetch data and send -transactions. - -Data from contracts is fetched using the `useContractValue` hook from @soroban-react/contracts. Transactions are submitted to the network -using the `useSendTransaction` from @soroban-react/contracts. diff --git a/components/ProviderExample.tsx b/components/ProviderExample.tsx deleted file mode 100644 index d78c2f7..0000000 --- a/components/ProviderExample.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import React from 'react' -import {SorobanReactProvider} from '@soroban-react/core'; -import {SorobanEventsProvider} from '@soroban-react/events'; -import {futurenet, sandbox, standalone} from '@soroban-react/chains'; -import {freighter} from '@soroban-react/freighter'; -import {ChainMetadata, Connector} from "@soroban-react/types"; - -const chains: ChainMetadata[] = [sandbox, standalone, futurenet]; -const connectors: Connector[] = [freighter()]; - - export default function ProviderExample({children}:{children: React.ReactNode}) { - return ( - - - {children} - - - ) - } \ No newline at end of file diff --git a/components/atoms/connect-button/index.tsx b/components/atoms/connect-button/index.tsx index 4457898..eb8bfa1 100644 --- a/components/atoms/connect-button/index.tsx +++ b/components/atoms/connect-button/index.tsx @@ -1,5 +1,5 @@ import React from 'react' -import { useSorobanReact } from '@soroban-react/core' +import { setAllowed } from '@stellar/freighter-api' import styles from './style.module.css' export interface ConnectButtonProps { @@ -8,16 +8,11 @@ export interface ConnectButtonProps { } export function ConnectButton({ label, isHigher }: ConnectButtonProps) { - const { connect } = useSorobanReact() - const openConnectModal = async () => { - await connect() - } - return ( diff --git a/components/molecules/deposits/index.tsx b/components/molecules/deposits/index.tsx index 00b9869..a42fb63 100644 --- a/components/molecules/deposits/index.tsx +++ b/components/molecules/deposits/index.tsx @@ -1,15 +1,8 @@ import React from 'react' -import * as SorobanClient from 'soroban-client' import styles from './style.module.css' import { Utils } from '../../../shared/utils' import { Spacer } from '../../atoms/spacer' -import * as convert from '../../../convert' -import { Constants } from '../../../shared/constants' -import { - ContractValueType, - useContractValue, -} from '@soroban-react/contracts' -import { useSorobanReact } from '@soroban-react/core' +import { balance as getBalance } from 'crowdfund-contract' export interface IDepositsProps { address: string @@ -20,19 +13,14 @@ export interface IDepositsProps { } export function Deposits(props: IDepositsProps) { - const useLoadDeposits = (): ContractValueType => { - return useContractValue({ - contractId: props.idCrowdfund, - method: 'balance', - params: [new SorobanClient.Address(props.address).toScVal()], - sorobanContext: useSorobanReact() - }) - } + const [balance, setBalance] = React.useState(BigInt(0)) + + React.useEffect(() => { + getBalance({ user: props.address }).then(setBalance) + }, [props.address]) - let yourDepositsXdr = useLoadDeposits() - const yourDeposits = convert.scvalToBigNumber(yourDepositsXdr.result) - if (yourDeposits.toNumber() <= 0) { + if (Number(balance) <= 0) { return } @@ -42,7 +30,7 @@ export function Deposits(props: IDepositsProps) {
You’ve Pledged
- {Utils.formatAmount(yourDeposits, props.decimals)}{' '} + {Utils.formatAmount(balance, props.decimals)}{' '} {props.symbol} {/* diff --git a/components/molecules/form-pledge/index.tsx b/components/molecules/form-pledge/index.tsx index b4102bc..22addf5 100644 --- a/components/molecules/form-pledge/index.tsx +++ b/components/molecules/form-pledge/index.tsx @@ -3,115 +3,94 @@ import { AmountInput, Button, Checkbox } from '../../atoms' import { TransactionModal } from '../../molecules/transaction-modal' import { Utils } from '../../../shared/utils' import styles from './style.module.css' -import { useSendTransaction, useContractValue, contractTransaction } from '@soroban-react/contracts' -import { useSorobanReact } from '@soroban-react/core' -import * as SorobanClient from 'soroban-client' -import BigNumber from 'bignumber.js' -import * as convert from '../../../convert' -import { Constants } from '../../../shared/constants' import { Spacer } from '../../atoms/spacer' -let xdr = SorobanClient.xdr +import { deposit } from 'crowdfund-contract' +import * as abundance from 'abundance-token' export interface IFormPledgeProps { account: string - tokenId: string - crowdfundId: string decimals: number - networkPassphrase: string symbol?: string + onPledge: () => void + updatedAt: number } export interface IResultSubmit { status: string - scVal?: SorobanClient.xdr.ScVal + value?: string + symbol?: string error?: string - value?: number - symbol?: string } -const FormPledge: FunctionComponent = props => { - const sorobanContext = useSorobanReact() - +/** + * Mint 100.0000000 tokens to the user's wallet for testing + */ +function MintButton({ account, symbol, onComplete, decimals }: { decimals: number, account: string; symbol: string, onComplete: () => void }) { + const [isSubmitting, setSubmitting] = useState(false) - // Call the contract to get user's balance of the token - const useLoadToken = (): any => { - return { - userBalance: useContractValue({ - contractId: Constants.TokenId, - method: 'balance', - params: [new SorobanClient.Address(props.account).toScVal()], - sorobanContext - }), - decimals: useContractValue({ - contractId: Constants.TokenId, - method: 'decimals', - sorobanContext - }), - symbol: useContractValue({ - contractId: Constants.TokenId, - method: 'symbol', - sorobanContext - }), - } - } + const displayAmount = 100 + const amount = BigInt(displayAmount * 10**decimals) - let token = useLoadToken() - const userBalance = convert.scvalToBigNumber(token.userBalance.result) - const tokenDecimals = - token.decimals.result && (token.decimals.result?.u32() ?? 7) - const tokenSymbol = - token.symbol.result && convert.scvalToString(token.symbol.result)?.replace("\u0000", "") + return ( +
- ) : null} {resultSubmit && ( - + setResultSubmit(undefined)} + /> )} ) - - // MintButton mints 100.0000000 tokens to the user's wallet for testing - function MintButton({ - account, - decimals, - symbol, - }: { - account: string - decimals: number - symbol: string - }) { - const [isSubmitting, setSubmitting] = useState(false) - const server = sorobanContext.server - const networkPassphrase = sorobanContext.activeChain?.networkPassphrase - - - const { sendTransaction } = useSendTransaction() - const amount = BigNumber(100) - - return ( -