--- tags: v3, scratch --- # Haus SDK Spec Rage ## Goals Create rage versions of new packages to make suggestions about - types of libraries and their concerns - project/folder structure - some initial examples of the api/interfaces for the SDK related libraries --- ### Libraries Recommend we break libraries into the following functional types: | UI | Features | Data-access | Utilities | | ------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- | -------------------------------------------- | -------------------------------------------------- | | purely presentational components | smart components wrapping data sdk, component library, web3 libraries | data fetching, transformation for the client | functions/utilities used across libraries and apps | | **@daohaus/ui** (the component library) | haus smart components ex: proposalList, connectWallet | **@daohaus/sdk**|**@daohaus/utils**| | | other ideas: redux wrapper, react hooks| | goal here to break up utilities into many smaller/hyper focussed pkgs, ex: local abis ***@daohaus/ui or @haus/ui*** I initially had some concerns that breaking these libraries into many small packages would increase the complexity of managing them, but I think our nx mono-repo makes this easier, and there are some solid benefits, ie) - easier for developers to understand what library to use and what it will do - smaller packages/bundles *This spec will continue with the data-access and utility library exploration only. find UI library details here:* [https://hackmd.io/Wk5hjmerSqKfXx0dp0DJfA](https://hackmd.io/Wk5hjmerSqKfXx0dp0DJfA) [https://hackmd.io/6Ei1TcsdSb2LQeQzW0jumQ](https://hackmd.io/6Ei1TcsdSb2LQeQzW0jumQ) --- ### Package structures #### @daohaus/haus-sdk scope This package will have a single class exposed. We can add smaller functional classes within that as needs emerge. **haus class** - inits the library w/ subclasses for scoped functionality **query class** - scoped/curated queries w/ full data hydration - ex: computing proposal status - can pull from multiple data sources - subgraphs, lambda/skynet cache, ceramic/idx, other 3rd party apis - queries grouped by functional area - user address, dao, proposals, members, vault data/balances - support /filtering on list queries - generic query function taking in raw graphql args - enables greater flexibility - urql wrapper taking typical query params - no hydration or light hydration because we can't predict the fields asked for - maybe just subgraph fields - user needs to handle pagination/filtering **other class ideas** - transaction - contract? expose some raw contract calls for getting - or does this belong in query? **utils directory** - utils hyper only used in sdk - requests - data transformation/hydration - gql queries **types directory** ##### folder structure ``` . ├── src/ │ ├── index.ts │ ├── query.ts │ ├── haus.ts │ ├── utils/ │ │ ├── index.ts │ │ ├── requests.ts │ │ └── someother-sdk-only-util.ts │ └── types/ │ └── index.ts │ └── some-type-domain.ts └── test/ └── some.spec.ts ``` *Base index.ts only imports/exports the haus class and types. * ```javascript import Haus from "./sdk"; export { Haus }; export * from "./types"; ``` ##### interface sketch ```javascript import Haus from '@daohaus/haus-sdk'; const haus = await Haus.create({ 0x64: 'some provider url', 0x4: 'some other provider url' }); const daoData = await haus.query.dao('some dao address', '0x64'); const userDaos = await haus.query.userDaos('some user address') const customQuery = await haus.graphQuery({ network: '0x64', query: SOME_GQL_QUERY, fields: 'id,createdAt,proposalId' }); ``` #### [rage repo](https://github.com/HausDAO/daohaus-rage/tree/rage/sdk/libs/haus-sdk-rage) --- #### @daohaus/haus-utils Grouped functions, constants, types - constants - legos - endpoints - contract addresses - contract abis - general contstant values grouped by functional area, ex: proposal types - utils - all reused utils (functions, anything else we find ourselves using often across apps) - **TODO: need to review V2 and upcoming V3 to try and get a larger list and organize by functional area. But some of these will emerge as we build** - would an audit be helpful at this point -- creating an ongoing list? - this can then become the TODO list and as folks are Raging/Saging they would mark it off the list -- it can then be added to our `utils` - types - we can add types as we identify ones that are useful across packages/apps ##### folder structure ``` . ├── src/ │ ├── index.ts │ ├── constants/ │ │ ├── index.ts │ │ ├── some-constants.ts │ │ └── some-other-grouped-constants.ts │ └── types/ │ ├── index.ts │ └── some-type-domain.ts └── test/ └── some.spec.ts ``` Base index.ts export * from all it's directories - makes every function available on it's own Directory index.ts export * from all it's friends - can not export anything here that we don't want exposed outside the library ##### interface sketch ```javascript import { encodeParams, PROPOSAL_STATUSES } from '@daohaus/haus-commons'; const encodedParams = encodeParams(someArgs); console.log(PROPOSAL_STATUSES) >>>> // { // unsponsored: 'Unsponsored', // voting: 'Voting', // grace: 'Grace', // expired: 'Expired', // cancelled: 'Cancelled', // needsProcessing: 'Ready for Processing', // failed: 'Failed', // passed: 'Passed', // actionFailed: 'Processing Failed', // unknown: 'Unknown', // }; ``` #### [rage repo](https://github.com/HausDAO/daohaus-rage/tree/rage/sdk/libs/haus-parlor) ## Pagination notes #### Query API: ```javascript= haus.query.listDaos({networkId: '0x5', pagination: {type: 'offset', pageSize: 100}}) haus.query.listDaos({networkId: '0x5', pagination: {type: 'cursor', pageSize: 100}}) // fetch all haus.query.listDaos({networkId: '0x5', pagination: {type: 'all'}}) ``` **types of pagination** offset: - can be used with any sort order - bad for large data sets - skip is limited ~6000 - poor performance - where: {id_gt: "0x3c56b96061bc34ba4d07d9bb1166b2297e1cf342-proposal-3"} - TODO: first might have an upper limit of 2000 we'd need to protect against cursor: - requires sort order to be on a field with ascending order - overrides sort by - sorts by id - throw error if they send an order all: - uses cursor pagination and loops through until no records are found #### Response ```typescript= export interface QueryResult<Data = any> { data?: Data; error?: HausError; networkId?: keyof Keychain; queryOptions: QueryOptions; pagination?: PaginationOptions; page?: number; fetchPrevious?: Function; fetchNext?: Function /// trackLastId on cursor } ``` - pagination - stores the original pagination object used in the query, updates in subsequent calls - 1st page: {type: 'offset', pageSize: 100, skip: 0} - 2nd page: {type: 'offset', first: 100, skip: 100} - we always up the 'first' by 1, but only return what was requested, so we can see if there is a next page or not - page: count the page up and down - fetch functions - null if there isn't another page - function definitions if there is to call the fetch again and update the pagination obkect and page count - can we provide a properly scoped sdk function in this res? ```javascript= const res = haus.query.listDaos({networkId: '0x5', filter: {dao: '0x0'}, pagination: {type: 'offset', first: 3, skip: 0}}) // { // data: proposals: [1,2,3], // networkId: '0x5', // queryOptions: {filter: {dao: '0x0'}}, // pagination: {type: 'offset', first: 3, skip: 0}, // page: 1, // fetchPrevious: null, // fetchNext: haus.query.fetchNext, // } // somthing like: const nextRes = res.fetchNext(res); // or const nextRes = haus.query.fetchNext(res); ``` ## Resoures [nx library types](https://nx.dev/structure/library-types) sdk tree https://tree.nathanfriend.io/?s=(%27options!(%27fancy4~fullPath!false~trailingSlash4~rootDot4)~6(%276%27src*index7sdk7haus7utils*0requests705other-sdk-only-util7types*05-type-domain32test*5.spec3222%27)~version!%271%27)*200%20%202%5Cn3.ts4!true5some6source!73*%017654320* commons tree https://tree.nathanfriend.io/?s=(%27options!(%27fancy5~fullPath!false~trailingSlash5~rootDot5)~8(%278%27src*67*20632s3other-grouped-2s7*type063type-domain74test*A.spec7444%27)~version!%271%27)*490s*92constant3.t0A-4%5Cn5!true6index7.ts8source!9%20%20Asome%01A987654320* [superfluid query class](https://github.com/superfluid-finance/protocol-monorepo/blob/dev/packages/sdk-core/src/Query.ts)