diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 00000000..81cb1efd --- /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 bafaa5c9..7a506119 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 d563d9e8..19de7116 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 d0f5180d..876b350d 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 9f3b8f51..1c6be9a8 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 46a0d6be..cadb8e4d 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 96497c09..3919581a 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 71f3a116..41fd693c 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 d78c2f74..00000000 --- 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 4457898e..eb8bfa12 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 00b9869c..a42fb63b 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 b4102bc5..22addf5b 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 ( -