diff --git a/src/lib/api/drips-subgraph/__generated__/DripsAccountsForUser.ts b/src/lib/api/drips-subgraph/__generated__/DripsAccountsForUser.ts new file mode 100644 index 00000000..b5f8db46 --- /dev/null +++ b/src/lib/api/drips-subgraph/__generated__/DripsAccountsForUser.ts @@ -0,0 +1,28 @@ +/* tslint:disable */ +/* eslint-disable */ +// @generated +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL query operation: DripsAccountsForUser +// ==================================================== + +export interface DripsAccountsForUser_dripsConfig_dripsAccount { + __typename: 'DripsAccount'; + isAccountDrip: boolean; + id: string; + account: any; +} + +export interface DripsAccountsForUser_dripsConfig { + __typename: 'DripsConfig'; + dripsAccount: DripsAccountsForUser_dripsConfig_dripsAccount[]; +} + +export interface DripsAccountsForUser { + dripsConfig: DripsAccountsForUser_dripsConfig | null; +} + +export interface DripsAccountsForUserVariables { + user: string; +} diff --git a/src/lib/api/drips-subgraph/__generated__/DripsEntiresStreamingToUser.ts b/src/lib/api/drips-subgraph/__generated__/DripsEntiresStreamingToUser.ts new file mode 100644 index 00000000..b8750ca7 --- /dev/null +++ b/src/lib/api/drips-subgraph/__generated__/DripsEntiresStreamingToUser.ts @@ -0,0 +1,24 @@ +/* tslint:disable */ +/* eslint-disable */ +// @generated +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL query operation: DripsEntiresStreamingToUser +// ==================================================== + +export interface DripsEntiresStreamingToUser_dripsEntries { + __typename: 'DripsEntry'; + user: any; + account: any; + amtPerSec: any; + isAccountDrip: boolean; +} + +export interface DripsEntiresStreamingToUser { + dripsEntries: DripsEntiresStreamingToUser_dripsEntries[]; +} + +export interface DripsEntiresStreamingToUserVariables { + user: any; +} diff --git a/src/lib/api/drips-subgraph/__generated__/DripsEntriesStreamingToUser.ts b/src/lib/api/drips-subgraph/__generated__/DripsEntriesStreamingToUser.ts new file mode 100644 index 00000000..01f8c049 --- /dev/null +++ b/src/lib/api/drips-subgraph/__generated__/DripsEntriesStreamingToUser.ts @@ -0,0 +1,24 @@ +/* tslint:disable */ +/* eslint-disable */ +// @generated +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL query operation: DripsEntriesStreamingToUser +// ==================================================== + +export interface DripsEntriesStreamingToUser_dripsEntries { + __typename: 'DripsEntry'; + user: any; + account: any; + amtPerSec: any; + isAccountDrip: boolean; +} + +export interface DripsEntriesStreamingToUser { + dripsEntries: DripsEntriesStreamingToUser_dripsEntries[]; +} + +export interface DripsEntriesStreamingToUserVariables { + user: any; +} diff --git a/src/lib/api/drips-subgraph/queries.ts b/src/lib/api/drips-subgraph/queries.ts index 1c2c75e8..24f5f242 100644 --- a/src/lib/api/drips-subgraph/queries.ts +++ b/src/lib/api/drips-subgraph/queries.ts @@ -1,44 +1,24 @@ import { gql } from 'graphql-tag'; -export const DRIPS_ENTRIES_FOR_CONFIG = gql` - query DripsEntriesForConfig($user: ID!) { +export const DRIPS_ACCOUNTS_FOR_USER = gql` + query DripsAccountsForUser($user: ID!) { dripsConfig(id: $user) { - dripsEntries { - receiver - account - amtPerSec + dripsAccount { isAccountDrip + id + account } } } `; -export const GET_LAST_DRIP_ENTRY = gql` - query LastDripsEntry($user: Bytes!) { - dripsEntries( - where: { user: $user, isAccountDrip: true } - orderBy: account - orderDirection: desc - first: 1 - ) { - account +export const DRIPS_ENTRIES_STREAMING_TO_USER = gql` + query DripsEntriesStreamingToUser($user: Bytes!) { + dripsEntries(where: { receiver: $user }) { user + account + amtPerSec isAccountDrip - receiver - } - } -`; - -export const GET_DRIPS_ACCOUNT = gql` - query DripsAccount($id: ID!) { - dripsAccount(id: $id) { - id - lastUpdatedBlockTimestamp - dripsEntries { - receiver - amtPerSec - } - balance } } `; diff --git a/src/lib/api/gnosis/index.ts b/src/lib/api/gnosis/index.ts deleted file mode 100644 index 5cb7723a..00000000 --- a/src/lib/api/gnosis/index.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { utils } from 'ethers'; - -const GNOSIS_API_SAFES_BASE: { [chainId: number]: string } = { - 4: 'https://safe-transaction.rinkeby.gnosis.io', - 1: 'https://safe-transaction.gnosis.io' -}; - -export async function getSafesForAddress(chainId: number, address: string) { - const ownedSafesReq = await fetch( - `${GNOSIS_API_SAFES_BASE[chainId]}/api/v1/owners/${utils.getAddress( - address - )}/safes/` - ); - const ownedSafesRes = await ownedSafesReq.json(); - - return ownedSafesRes?.safes ?? []; -} diff --git a/src/lib/components/AwaitingSafeTransactionStep.svelte b/src/lib/components/AwaitingSafeTransactionStep.svelte deleted file mode 100644 index b42f3ee0..00000000 --- a/src/lib/components/AwaitingSafeTransactionStep.svelte +++ /dev/null @@ -1,33 +0,0 @@ - - - - Continue in your safe -
-

- Head over to your Gnosis Safe, where you should find the transaction - request within the WalletConnect Safe App. After signing the transaction, - it will be proposed to your safe. -

-

- Once quorum has been reached and the transaction is executed, the - Workstreams UI will update accordingly. -

-
-
- -
-
- - diff --git a/src/lib/components/BalanceButton.svelte b/src/lib/components/BalanceButton.svelte index 3e1a5d11..fa3db7a7 100644 --- a/src/lib/components/BalanceButton.svelte +++ b/src/lib/components/BalanceButton.svelte @@ -7,19 +7,15 @@ import * as modal from '$lib/utils/modal'; import drips from '$lib/stores/drips'; import { currencyFormat, padFloatString } from '$lib/utils/format'; - import { workstreamsStore } from '$lib/stores/workstreams'; + import workstreamsStore from '$lib/stores/workstreams'; import LoadingDots from './LoadingDots.svelte'; import { goto } from '$app/navigation'; import StepperModal from '$lib/components/StepperModal/index.svelte'; import Intro from '$lib/components/WithdrawSteps/Intro.svelte'; - import { walletStore } from '$lib/stores/wallet/wallet'; - import AwaitingSafeTransactionStep from './AwaitingSafeTransactionStep.svelte'; - - const estimates = workstreamsStore.estimates; $: currentCycleBalanceEstimate = - $estimates.earnedInCurrentCycle !== undefined && - currencyFormat($estimates.earnedInCurrentCycle); + $workstreamsStore.earnedInCurrentCycle !== undefined && + currencyFormat($workstreamsStore.earnedInCurrentCycle); $: withdrawable = $drips.collectable && currencyFormat($drips.collectable.wei); @@ -30,7 +26,7 @@ currentCycleBalanceEstimate && currencyFormat( ($drips.collectable?.wei ?? BigInt(0)) + - ($estimates.earnedInCurrentCycle?.wei ?? BigInt(0)) + ($workstreamsStore.earnedInCurrentCycle?.wei ?? BigInt(0)) ); $: formattedCycleEnd = $drips.cycle && { @@ -48,7 +44,7 @@ async function collect() { modal.show(StepperModal, undefined, { - steps: [Intro, $walletStore.safe?.ready && AwaitingSafeTransactionStep] + steps: [Intro] }); } diff --git a/src/lib/components/Connect/Button.svelte b/src/lib/components/Connect/Button.svelte index 57633a91..20fd95eb 100644 --- a/src/lib/components/Connect/Button.svelte +++ b/src/lib/components/Connect/Button.svelte @@ -9,7 +9,6 @@ import LoadingDots from '../LoadingDots.svelte'; import StepperModal from '../StepperModal/index.svelte'; import ChooseWallet from './steps/ChooseWallet.svelte'; - import LinkSafe from './steps/LinkSafe.svelte'; import clearStores from '$lib/stores/utils/clearStores'; import connectStores from '$lib/stores/utils/connectStores'; import isMobile from '$lib/stores/isMobile'; @@ -29,7 +28,7 @@ hover = false; }, { - steps: [ChooseWallet, LinkSafe] + steps: [ChooseWallet] } ); } @@ -38,8 +37,7 @@ await tick(); if ($walletStore.ready) { - const { provider: localProvider, safe } = $walletStore; - const provider = safe?.provider ?? localProvider; + const { provider } = $walletStore; if (!provider) throw new Error('Unable to get provider'); diff --git a/src/lib/components/Connect/steps/LinkSafe.svelte b/src/lib/components/Connect/steps/LinkSafe.svelte deleted file mode 100644 index eb5a1028..00000000 --- a/src/lib/components/Connect/steps/LinkSafe.svelte +++ /dev/null @@ -1,128 +0,0 @@ - - -{#if safeAddresses} - - Link your Gnosis Safe -
- {#if safeAddresses.length > 1} -
- ({ - title: formatAddress(a), - value: a - }))} - /> -
- {:else} -
- {/if} -

- We detected a Gnosis Safe associated with your account. If you link it, - you'll be interacting with Workstreams on behalf of your safe, and all - transactions will require a quorum. -

-

- To connect, open the WalletConnect Safe App - within your Gnosis Safe by navigating to - Apps - → - WalletConnect. Then, press - Connect safe - below, copy the connection URL to your clipboard, and paste it into the connection - link field in the WalletConnect Safe App. -

-

- If you skip this, you'll be using Workstreams with your - previously-connected wallet. -

-
-
- - -
-
-{:else} - -{/if} - - diff --git a/src/lib/components/CreateModal.svelte b/src/lib/components/CreateModal.svelte index f8736693..a8c44d64 100644 --- a/src/lib/components/CreateModal.svelte +++ b/src/lib/components/CreateModal.svelte @@ -9,17 +9,13 @@ import * as modal from '$lib/utils/modal'; import Modal from '$components/Modal.svelte'; - import { getConfig } from '$lib/config'; - import { - Currency, - WorkstreamState, - type Workstream, - type WorkstreamInput - } from '$lib/stores/workstreams/types'; import { utils } from 'ethers'; - import { workstreamsStore } from '$lib/stores/workstreams'; + import workstreamsStore from '$lib/stores/workstreams'; import ensNames from '$lib/stores/ensNames'; import { walletStore } from '$lib/stores/wallet/wallet'; + import drips from '$lib/stores/drips'; + import { cidToBase10 } from '$lib/utils/cid'; + import { toWei } from 'drips-sdk'; const durationOptions = [ { value: '1', title: 'Days' }, @@ -106,6 +102,9 @@ async function createWorkstream() { creatingWorkstream = true; + const { address } = $walletStore; + if (!address) throw new Error('Connect wallet first'); + const daiPerDay = parseInt(total) / (parseInt(duration) * parseInt(durationUnit)); const weiPerDay = utils.parseUnits(daiPerDay.toString()); @@ -114,31 +113,39 @@ const chainId = $walletStore.network?.chainId; if (!chainId) throw new Error('Unable to determine chain ID'); - - let input: WorkstreamInput = { - ratePerSecond: { - currency: Currency.DAI, - wei: weiPerSecond.toString() - }, - title, - desc: description, - chainId, - durationDays: parseInt(duration) * parseInt(durationUnit), - assignTo: assigneeAddress, - state: WorkstreamState.ACTIVE - }; + if (!assigneeAddress) throw new Error('Assignee address is missing'); try { - const res = await fetch(`${getConfig().API_URL_BASE}/workstreams`, { - method: 'POST', - credentials: 'include', - body: JSON.stringify(input) + const cid = await workstreamsStore.createWorkstream({ + creator: address, + amountPerSecond: { + currency: 'dai', + wei: weiPerSecond.toBigInt() + }, + streamTarget: { + currency: 'dai', + wei: weiPerDay.toBigInt() * BigInt(parseInt(duration)) + }, + title, + description, + createdAt: new Date(), + receiver: assigneeAddress }); - const workstream: Workstream = await res.json(); + const call = await drips.createDrip( + assigneeAddress, + { + currency: 'dai', + wei: weiPerSecond.toBigInt() + }, + BigInt(cidToBase10(cid)), + toWei('10').toBigInt() + ); + + await call.tx.wait(1); // Push the new workstream into the state so it shows up on the dashboard. - await workstreamsStore.getWorkstream(workstream.id); + await workstreamsStore.fetchWorkstream(cid.toString()); } catch (e) { return; } diff --git a/src/lib/components/Header.svelte b/src/lib/components/Header.svelte index 1a577404..09cac914 100644 --- a/src/lib/components/Header.svelte +++ b/src/lib/components/Header.svelte @@ -62,7 +62,7 @@ >
- {#if $walletStore.ready && onDashboard} + {#if $walletStore?.ready && onDashboard}
{/if} - {#if $walletStore.ready} + {#if $walletStore?.ready}
diff --git a/src/lib/components/History/EarnedInbetweenDropdown/Content.svelte b/src/lib/components/History/EarnedInbetweenDropdown/Content.svelte index 521e5077..fe9921e9 100644 --- a/src/lib/components/History/EarnedInbetweenDropdown/Content.svelte +++ b/src/lib/components/History/EarnedInbetweenDropdown/Content.svelte @@ -1,6 +1,6 @@ diff --git a/src/lib/components/PauseStreamSteps/PauseUnpause.svelte b/src/lib/components/PauseStreamSteps/PauseUnpause.svelte index 40f12854..f84e5705 100644 --- a/src/lib/components/PauseStreamSteps/PauseUnpause.svelte +++ b/src/lib/components/PauseStreamSteps/PauseUnpause.svelte @@ -4,11 +4,9 @@ import * as modal from '$lib/utils/modal'; import StepContent from '../StepContent.svelte'; - import { - workstreamsStore, + import workstreamsStore, { type EnrichedWorkstream } from '$lib/stores/workstreams'; - import { walletStore } from '$lib/stores/wallet/wallet'; import drips from '$lib/stores/drips'; import type { AwaitPendingPayload } from '../StepperModal/types'; @@ -23,20 +21,10 @@ $: actionLabel = action.charAt(0).toUpperCase() + action.slice(1); function pauseUnpause() { - const isSafe = $walletStore.safe?.ready; - const waitFor = async () => { - if (isSafe) { - drips.pauseUnpause(action, enrichedWorkstream); - } else { - const tx = await drips.pauseUnpause(action, enrichedWorkstream); - await tx.wait(1); - await workstreamsStore.getWorkstream( - enrichedWorkstream.data.id, - undefined, - true - ); - } + const tx = await drips.pauseUnpause(action, enrichedWorkstream); + await tx.wait(1); + await workstreamsStore.fetchWorkstream(enrichedWorkstream.cid); }; dispatch('awaitPending', { diff --git a/src/lib/components/Rate.svelte b/src/lib/components/Rate.svelte index 8fc35962..aae95ed0 100644 --- a/src/lib/components/Rate.svelte +++ b/src/lib/components/Rate.svelte @@ -1,5 +1,5 @@ - -
- -
- - diff --git a/src/lib/components/SetUpPaymentSteps/steps/ConfirmValues.svelte b/src/lib/components/SetUpPaymentSteps/steps/ConfirmValues.svelte deleted file mode 100644 index d0357a01..00000000 --- a/src/lib/components/SetUpPaymentSteps/steps/ConfirmValues.svelte +++ /dev/null @@ -1,177 +0,0 @@ - - -
- -

Set up payment stream

-

Here's the drips config we're gonna set up.

-
-
-

Streaming to

- -
- -
-
-
-
-
-

Total amount

- - -
-
-

Stream rate

-

- {daiPerDay} DAI / 24h -

-
-
-
-
-

Top up amount

- -
-
-
- -
- - diff --git a/src/lib/components/SetUpPaymentSteps/steps/Intro.svelte b/src/lib/components/SetUpPaymentSteps/steps/Intro.svelte deleted file mode 100644 index 0220cfb4..00000000 --- a/src/lib/components/SetUpPaymentSteps/steps/Intro.svelte +++ /dev/null @@ -1,47 +0,0 @@ - - -
- -

Set up payment stream

-
-

Here's how this works:

-
    -
  1. 1. Create the stream & top up it up with an initial amount.
  2. -
  3. - 2. Funds starts streaming at the predefined rate until your initial top - up runs out. -
  4. -
  5. 3. Top up the balance to resume streaming.
  6. -
-

If you want to pause a stream, you can drain the topped up amount.

-
- -
- - diff --git a/src/lib/components/SetUpPaymentSteps/steps/SetDaiAllowance.svelte b/src/lib/components/SetUpPaymentSteps/steps/SetDaiAllowance.svelte deleted file mode 100644 index cc3cddf3..00000000 --- a/src/lib/components/SetUpPaymentSteps/steps/SetDaiAllowance.svelte +++ /dev/null @@ -1,69 +0,0 @@ - - -
- -

Grant permissions

- {#if approvalGranted === false} - You need to allow the Drips contract to spend your DAI. - - {:else if approvalGranted === undefined} - - {/if} -
- - diff --git a/src/lib/components/SetUpPaymentSteps/steps/gnosis-safe/ConfirmValues.svelte b/src/lib/components/SetUpPaymentSteps/steps/gnosis-safe/ConfirmValues.svelte deleted file mode 100644 index 74da1f16..00000000 --- a/src/lib/components/SetUpPaymentSteps/steps/gnosis-safe/ConfirmValues.svelte +++ /dev/null @@ -1,172 +0,0 @@ - - -
- -

Set up payment stream

-

- Customize your stream below. When you confirm, the Workstream will be - activated, but it will only start streaming funds once the setup transaction - has been executed by your connected Gnosis Safe. -

-
-
-

Streaming to

- -
- -
-
-
-
-
-

Total amount

- - -
-
-

Stream rate

-

- {daiPerDay} DAI / 24h -

-
-
-
-
-

Top up amount

- -
-
-
- -
- - diff --git a/src/lib/components/SetUpPaymentSteps/steps/gnosis-safe/SetDaiAllowance.svelte b/src/lib/components/SetUpPaymentSteps/steps/gnosis-safe/SetDaiAllowance.svelte deleted file mode 100644 index f068fc55..00000000 --- a/src/lib/components/SetUpPaymentSteps/steps/gnosis-safe/SetDaiAllowance.svelte +++ /dev/null @@ -1,74 +0,0 @@ - - -
- -

Grant permissions

- {#if approvalGranted === false} -

- You need to allow the Radicle Drips contract to access the DAI in your - Gnosis Safe before creating a stream. After clicking Allow drips contract - below, you'll find a transaction prompt within the Gnosis Safe app. After you - sign the transaction and it reaches quorum and is executed by your safe, re-trigger - the payment setup flow and you'll be able to proceed. -

-

You only have to do this once.

- - {:else if approvalGranted === undefined} - - {/if} -
- - diff --git a/src/lib/components/SetUpPaymentSteps/steps/gnosis-safe/WaitingForConfirmation.svelte b/src/lib/components/SetUpPaymentSteps/steps/gnosis-safe/WaitingForConfirmation.svelte deleted file mode 100644 index 8d0f980a..00000000 --- a/src/lib/components/SetUpPaymentSteps/steps/gnosis-safe/WaitingForConfirmation.svelte +++ /dev/null @@ -1,25 +0,0 @@ - - - - Continue in your Gnosis Safe -
-

- Your workstream won't start streaming funds until the proposed transaction - reaches quorum and is executed by your Gnosis Safe. Head over to your safe - now, sign the transaction, and execute it after it's reached quorum.
You can re-propose the transaction anytime by clicking on "Set up stream" - again. -

-
-
- -
-
diff --git a/src/lib/components/TimeRate.svelte b/src/lib/components/TimeRate.svelte index 05a7af57..61e9945d 100644 --- a/src/lib/components/TimeRate.svelte +++ b/src/lib/components/TimeRate.svelte @@ -1,27 +1,23 @@
- -

for {timeframeFormat(workstream.durationDays)}

+
diff --git a/src/lib/components/TitleMeta.svelte b/src/lib/components/TitleMeta.svelte index 2a7a69ba..21adad8e 100644 --- a/src/lib/components/TitleMeta.svelte +++ b/src/lib/components/TitleMeta.svelte @@ -1,16 +1,16 @@

- {workstream.title} + {enrichedWorkstream.data.title}

- +
+--> diff --git a/src/routes/workstream/[id].svelte b/src/routes/workstream/[id].svelte index 7f36f33e..4e488d75 100644 --- a/src/routes/workstream/[id].svelte +++ b/src/routes/workstream/[id].svelte @@ -1,41 +1,15 @@ - - - {workstream?.title ?? 'Workstream'} + {enrichedWorkstream?.data.title ?? 'Workstream'} -{#if workstream} - +{#if enrichedWorkstream} + {:else}

Sorry couldn't load the details of this Workstream.

{/if}