Code Monkey home page Code Monkey logo

aragon's People

Contributors

0x-r4bbit avatar 2color avatar aquigorka avatar bingen avatar bpierre avatar deamme avatar decodedbrain avatar delfipolito avatar drcmda avatar ewingrj avatar gasolin avatar izqui avatar joejordan avatar john-light avatar juslar avatar jvluso avatar kernelwhisperer avatar luisivan avatar markgeeromano avatar mateotomas2 avatar mul53 avatar onbjerg avatar ottodevs avatar rperez89 avatar rudygodoy avatar schwartz10 avatar smokyish avatar sohkai avatar stellarmagnet avatar uniconstructor avatar

Stargazers

 avatar

Watchers

 avatar  avatar  avatar

aragon's Issues

Edit organization token settings

Description

Allow members of an organization to view the properties for each of their organization tokens, and to add additional details such as a description of the token's utility and a logo.

Test forwarder API in dot-voting

Once the forwarder API has been implemented connect dot voting so that forwarded actions are registered in the forwarder API.

Add info component on gas prices in the onboarding

Add a warning info component in the "Review information" section before launching your organization where to inform the organization administrator about gas prices and how to set up a moderate gas price for a smooth setup before clicking on moving onto the final step.

There are two versions for this message depending on whether the user's Ethereum Provider is or isn't MetaMask. Text specifications available here. Link would direct users to the troubleshooting Help Scout documentation.

Figma file available here.

D 1 0 - Review information

Update Onboarding template info component

Info component

  • This component should take on a “warning” style, as per the designs.
  • The text should be updated, as per the designs. The hyperlink should open this link in a new tab, where we’ll eventually have further related to improving the onboarding experience.
  • Only display the sentence that says “Additionally, do not use the "Speed Up" MetaMask feature, otherwise it will result in configuration errors.” if the Ethereum provider is MetaMask

Design reference

Connect client to Storage app

Since we've determined that making a kernel level change is not the best course of action the home app setting (and all other organization settings) will need to be stored in a contract-only storage application (we may want to eventually build out a UI, but for now just the client level UI should be sufficient). When the client parses through the connected apps, it will need to save the default (when multiple apps of the same type are installed a default application can be set, use this one) storage application and provide this in the react state. A function will then need to be passed into the settings component that calls the Storage function registerData(bytes32 key, string value) on the storage application.

Set and get data wrapper functions

BRANCH OFF feat/storage-tab for this one, then PR it into feat/storage-tab

set data function:

const setData = async (key, obj) => {
  /*
    1. take the obj and dag put it based on the IPFS node provider
    2. get back the `cid` of the object dag putted to IPFS
    3. call the smartContract.registerData function, passing it `(key, cid)`
  */
}

get data function:

const getData = async (key) => {
  /*
    1. take the key and call the smartContract.getData function, passing it `(key)`
    2. receive the `cid` from the function call above
    3. `dag.get` the cid received in step 2 to get back the object
    4. return the object 
  */
}

The above functions should be defined in the IpfsStorageContext and they should be memoized using useCallback similar to updateIpfsProvider (with a dependency array - i think the only dependencies in that array will be the smart contract and the ipfs object). So this should look something like:

const setData = useCallback((key, obj) => {
  const set = async () => {
    const cid = await ipfsStore.ipfsEndpoints.dagPut(obj)
    await storageContract.registerData(key, cid)
  }
  set()
}, [ipfsStore.ipfsEndpoints, storageContract])

and

const getData = useCallback((key) => {
  const get = async () => {
    const cid = await storagegContract.getData(key)
    const obj = await ipfsStore.ipfsEndpoints.getData(cid)
    return obj
  }
  get()
}, [ipfsStore.ipfsEndpoints, storageContract])

It should then be passed in the context: https://github.com/AutarkLabs/aragon/blob/feat/storage-tab/src/contexts/IpfsStorageContext.js#L302 and exposed in the useIpfs hook

No aragon storage app installed handlingg

A "you need to install an aragon-storage app to use this feature" screen

@jayalaves we'll just implement something quickly and you can tighten up the design when you're ready

Repin organization settings upon switching IPFS provider

This should wait until the organization settings have progressed a bit further. But here's the general idea:

  1. a user pins their organization settings to a provider (say aragon association node)
  2. a user elects to change their org ipfs provider
  3. behind the scenes, we find the cid associated with the org settings, dag.get the organization settings from the old ipfs provider, save the object in memory, switch to the new provider, and repin the org settings there.

Some challenges:

we need to make sure the cid that comes back is the same

Tying together the moving pieces for IPFS storage

@listenaddress @radio-alice now is a good time to start putting together all the moving pieces you both have been working on within this repository.

Goals:

  • Create a global redux-esque store to hold our IPFS obj, the IPFS obj's various states (connecting, connected, connectedSuccess, error) and the storage smart contract.
  • Instantiate the storage smart contract and IPFS node with right provider on page load

We can call this feature: "Creating an IPFS Storage global store". At a very high level, here's how the architecture looks:

IMG_1198

How to get this done:

Creating any global variables that are accessible to any children components can be done through the use of react context. React provides a really nice useContext hook for this.

Context has a Provider and a Consumer - the Provider is essentially serving as that "global store" and the Consumer is pulling values from that global store. As long as the Consumer is rendered inside the Provider in a react render tree - the Consumer will have access to the Provider's context.

Let's use an example from the the Discussions aragon app - where the entire discussion state is held in context.

First, we need to actually create a new "store", via createContext: https://github.com/AutarkLabs/planning-suite/blob/dev/apps/discussions/app/modules/Discussions.js#L6

Next, (ignore all the logic in the useEffect hook for now) and just focus on the Provider component that is returned. Notice 2 things:

  1. it gets passed a value prop - whatever gets passed to value then becomes available to the Consumer child components (the value is the global store!)
  2. It's composed as a wrapper component (aka, the Provider component renders a prop called children). A component that renders children just makes a react component look more like a native html component:
const Wrapper = (props) => {
   return <div>{props.children}<div>
}

<Wrapper>
   {...} // entire react tree can go inside Wrapper component, and it will get rendered!
</Wrapper>

It's important that our Provider Wrapper component is high enough in this aragon client render tree because only components rendered inside of it will be valid Consumer's of the Provider Wrapper's context. I'd recommend rendering the Wrapper component as high as possible in the render tree, right around here

Third, we want to collect data and store it as one big object, which gets passed to the Provider Wrapper through the value prop.

So initially, our value object might look something like this:

const storageContextStore = {
   ipfsObj = null,
   connectingToIpfsObj = false,
   connectedToIpfsObjSuccessfully = false,
   connectedToIpfsObjFailure = false,
   storageContract = null,
}

This might look something like:

import React, { createContext } from 'react'

export const IPFSStorageContext = createContext({})

export const IPFSStorageProvider = ({children}) => {
  const storageContextStore = {
   ipfsObj = null,
   connectingToIpfsObj = false,
   connectedToIpfsObjSuccessfully = false,
   connectedToIpfsObjFailure = false,
   storageContract = null,
  }

  return (
    <IPFSStorageContext.Provider value={{ ...storageContextStore }}>
      {children}
    </IPFSStorageContext.Provider>
  )
}

When we pass this storageContextStore in as a value prop to our Provider Wrapper, we make it available to any children rendered inside the Provider Wrapper.

Fourth, we need to actually fetch the data, and set the variables that are getting passed in to the Provider's value prop. This is what the logic inside useEffect is doing within the Discussions Context: https://github.com/AutarkLabs/planning-suite/blob/dev/apps/discussions/app/modules/Discussions.js#L14

Here's how that process can go down. Upon page load:

  1. Initiate the aragon-storage contract (here's an example of how we're already doing that):
    a. (Find the proxy address of the storage app)
    b. Instantiate the storage contract via the instantiateStorageContract function ,passing it the proxy address of the storage-contract and the aragon wrapper instance https://github.com/AutarkLabs/aragon/blob/feat/storage-tab/src/apps/Organization/Storage.js#L113

  2. Fetch the value of the storage provider from our smart contract

  3. Depending on which provider is selected, get the proper credentials from the aragon-cache (@radio-alice was working on this). Only Pinata and Temporal.Cloud require credentials

  • q: how should we handle the situation when we fetch the provider from the smart contract, go get the credentials from aragon cache, but they don't exist? Should we throw an error? What should our "redux-esque" store show in terms of state?
  1. If all the necessary information is fetched (including credentials), instantiate the IPFS-esque object that @radio-alice made, passing in the necessary information

  2. set the state value of the variables passed in to the Provider Wrapper. You could use the useState hook for this, but you could also provide more flexibility by using the useReducer hook here.

All together, this might look something like:

import React, { useState, createContext } from 'react'

export const IPFSStorageContext = createContext({})

const initialStorageContextValue = {
   ipfsObj = null,
   connectingToIpfsObj = false,
   connectedToIpfsObjSuccessfully = false,
   connectedToIpfsObjFailure = false,
   storageContract = null,
}

export const IPFSStorageProvider = ({children}) => {
  const [storageContextStore, setStorageContextStore] = useState(initialStorageContextValue)
  useEffect(() => {
      const storage = fetchAndConfigureAllTheThings() // fetch and configure all the necessary things
      setStorageContextStore(fetchAndConfigureAllTheThings)
  })
  return (
    <IPFSStorageContext.Provider value={{ ...storageContextStore }}>
      {children}
    </IPFSStorageContext.Provider>
  )
}

And that's it for now!

Next up we'll write a custom hook to get and set values in our newly created context store.

Notify Receiver API

Once a forwarder action has been registered with the client must emit to the receiver observable so that the receiver app has knowledge of the pending forwarded action. This should path through the aragon-api.

Receive aragon-api sender information in client

Once the sender API has received information on a forwarded action Aragon client should then take this information, register it based on the app that sent it.

The information the client should expect to receive is:
An ID (e.g. voteId)
The “target” action, including address and calldata (would require decoding and unwrapping EVMScripts)
(Perhaps optional) The execution path left (would require decoding and unwrapping EVMScripts)

Ability to set a custom aragon apm URI for home tab

Currently the home app routes to the root URL for the application, instead we want to provide the ability to route to a specific application. This routing should default to the current home application, and only become active if a home app is specifically set.
The routing is currently handled in /src/routing.js#L90.
This will require modifying that function to leverage a client or contract level setting for how to route home, and providing hooks to change this setting elsewhere in the client.
In order to make those changes, the local-settings.js file will need to accommodate a home app selector. This will also require changing the settings component to provide the correct UI to make these changes.
Since the routing.js function is called from the wrapper, it would be best to handle the loading of local state settings in the wrapper so that no state needs to be loaded in the routing.js file. Using a contract based solution we would pull this information through subscription to the wrapper, which is detailed below.
Once all of this is taken care of we'll have the ability to set a new home app locally but in order for the change to persist it needs to be performed on the kernel.

To have the home app URI persist it makes the most sense to add a function/field to the kernel contract similar to how setting a recovery vault is handled The exact implementation depends on how we want to handle subscription to this information as detailed below.
In order to get the URI set and pulled from the kernel it will be necessary to interact with the contract sets through the wrapper (The one created in App.js not the component) similar to how app upgrades are handled. In a standard DAO this transaction routing should be fairly straight forward but using the correct path is still important to accommodate for vote based home URI changes or more complex permission structures. The correct handler for an update to the home app URI will also need to be added in the wrapper initialization in App.js and the changes will need to be subscribed to

Update: Since we've determined that making a kernel level change is not the best course of action the home app setting (and all other organization settings) will need to be stored in a contract-only storage application (we may want to eventually build out a UI, but for now just the client level UI should be sufficient). Since we're handling it this way we can handle the custom home tab through consumption of external contract events without the need to make modifications to aragon.js. If the storage app is not loaded, the settings changes should prompt the user to install this application. If the storage app is loaded the wrapper should parse a uniquely identified storage element based on storage events and interpret it as the home app.

The storage application should generate events of the form Registered(Bytes32 key) and for the initial home app settings we can use keccak256("DEFAULT_HOME_APP") as the key.

Since there isn’t an observable to subscribe to in aragon.js currently we either need to: create another observable to handle the change of a home app or, attach a flag to the app instance that is being used for the home application which we can handle when we respond to changes in the application stream.

Design

  • Add a "Home Page" section in the Settings app, below the Organization address section. Here, the user can select another home app from a dropdown menu.
  • There should be an option "Use the default" which will be the existing home app and hence the default option that is selected.
  • If they select another app, then the existing "Home" app will not be displayed.
  • There will be an additional input where the user can rename the tab. By default this will be Home. This means if the user chooses "Voting" then the tab name will show up as Home unless they rename the tab.

image

Test receiver API in alllocations

Once the forwarder API has been implemented, add the receiver observable to the projects script.js to register pending votes for issue curation.

Add User Interface for settings default home app

Design

  • Add a "Home Page" section in the Settings app, below the Organization address section. Here, the user can select another home app from a dropdown menu.
  • There should be an option "Use the default" which will be the existing home app and hence the default option that is selected.
  • If they select another app, then the existing "Home" app will not be displayed.
  • There will be an additional input where the user can rename the tab. By default this will be Home. This means if the user chooses "Voting" then the tab name will show up as Home unless they rename the tab.

image

Animate signature progress and add time remaining

The current loader screen while an organization is setting up doesn't provide enough feedback for the user to have any expectation of when it'll be ready. See in my video here.

The signature steps are meant to be animated circular progress bars reflecting estimated time remaining (as per Aragon One's design files). We should facilitate an animation in sync with this estimate and reflect the time remaining underneath the signature name.

Figma file available here.

D 1 1 - Loader

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.