import fetch from 'cross-fetch' ; import { Web3Provider } from '@ethersproject/providers' ; import { Wallet } from '@ethersproject/wallet' ; import { Space , Proposal , CancelProposal , Vote , Follow , Unfollow , Subscribe , Unsubscribe , Alias , spaceTypes , proposalTypes , cancelProposalTypes , cancelProposal2Types , voteTypes , voteArrayTypes , voteStringTypes , vote2Types , voteArray2Types , voteString2Types , followTypes , subscribeTypes , unfollowTypes , unsubscribeTypes , aliasTypes } from './types' ; import hubs from '../hubs.json' ; const NAME = 'snapshot' ; const VERSION = '0.1.4' ; export const domain = { name : NAME , version : VERSION } ; export default class Client { readonly address : string ; constructor ( address = hubs [ 0 ] ) { this . address = address ; } async sign ( web3 , address , message , types ) { const signer = web3 ?. getSigner ? web3 . getSigner ( ) : web3 ; if ( ! message . from ) message . from = address ; if ( ! message . timestamp ) message . timestamp = parseInt ( ( Date . now ( ) / 1e3 ) . toFixed ( ) ) ; const data = { domain , types , message } ; const sig = await signer . _signTypedData ( domain , data . types , message ) ; console . log ( 'Sign' , { address , sig , data } ) ; return await this . send ( { address , sig , data } ) ; } async send ( envelop ) { const url = `${ this . address }/api/msg` ; const init = { method : 'POST' , headers : { Accept : 'application/json' , 'Content-Type' : 'application/json' } , body : JSON . stringify ( envelop ) } ; return new Promise ( ( resolve , reject ) => { fetch ( url , init ) . then ( ( res ) => { if ( res . ok ) return resolve ( res . json ( ) ) ; throw res ; } ) . catch ( ( e ) => e . json ( ) . then ( ( json ) => reject ( json ) ) ) ; } ) ; } async space ( web3 , address , message ) { return await this . sign ( web3 , address , message , spaceTypes ) ; } async proposal ( web3 , address , message ) { return await this . sign ( web3 , address , message , proposalTypes ) ; } async cancelProposal ( web3 , address , message ) { const type2 = message . proposal . startsWith ( '0x' ) ; return await this . sign ( web3 , address , message , type2 ? cancelProposal2Types : cancelProposalTypes ) ; } async vote ( web3 , address , message ) { const type2 = message . proposal . startsWith ( '0x' ) ; let type = type2 ? vote2Types : voteTypes ; if ( [ 'approval' , 'ranked-choice' ] . includes ( message . type ) ) type = type2 ? voteArray2Types : voteArrayTypes ; if ( [ 'quadratic' , 'weighted' ] . includes ( message . type ) ) { type = type2 ? voteString2Types : voteStringTypes ; message . choice = JSON . stringify ( message . choice ) ; } delete message . type ; return await this . sign ( web3 , address , message , type ) ; } async follow ( web3 , address , message ) { return await this . sign ( web3 , address , message , followTypes ) ; } async unfollow ( web3 , address , message ) { return await this . sign ( web3 , address , message , unfollowTypes ) ; } async subscribe ( web3 , address , message ) { return await this . sign ( web3 , address , message , subscribeTypes ) ; } async unsubscribe ( web3 , address , message ) { return await this . sign ( web3 , address , message , unsubscribeTypes ) ; } async alias ( web3 , address , message ) { return await this . sign ( web3 , address , message , aliasTypes ) ; } }