import Web3 from 'web3' ; import { AddressKeys , getAddress , protocolVersions } from '../contracts/addresses' ; import { AbiItem } from 'web3-utils' ; import { satisfies } from 'semver' ; import mapKeys from 'lodash/mapKeys' ; import { LayerTwoOracle , layerTwoOracleMeta } from './layer-two-oracle' ; import Safes from './safes' ; import { PrepaidCard , prepaidCardMeta } from './prepaid-card' ; import { PrepaidCardMarket , prepaidCardMarketMeta } from './prepaid-card-market' ; import Assets from './assets' ; import LayerOneOracle from './layer-one-oracle' ; import TokenBridgeHomeSide from './token-bridge-home-side' ; import TokenBridgeForeignSide from './token-bridge-foreign-side' ; import { revenuePoolMeta , RevenuePool } from './revenue-pool' ; import { rewardPoolMeta , RewardPool } from './reward-pool' ; import { rewardManagerMeta , RewardManager } from './reward-manager' ; import HubAuth from './hub-auth' ; import { SUPPORTED_ABIS } from '../generated/supported-abis' ; export type SDK = 'Assets' | 'LayerOneOracle' | 'LayerTwoOracle' | 'PrepaidCard' | 'PrepaidCardMarket' | 'RevenuePool' | 'Safes' | 'HubAuth' | 'TokenBridgeHomeSide' | 'TokenBridgeForeignSide' | 'RewardPool' | 'RewardManager' ; export type MapReturnType < T > = T extends 'Assets' ? Assets : T extends 'HubAuth' ? HubAuth : T extends 'LayerOneOracle' ? LayerOneOracle : T extends 'LayerTwoOracle' ? LayerTwoOracle : T extends 'PrepaidCard' ? PrepaidCard : T extends 'PrepaidCardMarket' ? PrepaidCardMarket : T extends 'RevenuePool' ? RevenuePool : T extends 'RewardPool' ? RewardPool : T extends 'RewardManager' ? RewardManager : T extends 'Safes' ? Safes : T extends 'TokenBridgeHomeSide' ? TokenBridgeHomeSide : T extends 'TokenBridgeForeignSide' ? TokenBridgeForeignSide : never ; export interface ContractMeta { apiVersions : Record < string , any > ; contractName : AddressKeys ; } const cardPayVersionABI = [ { constant : true , inputs : [ ] , name : 'cardpayVersion' , outputs : [ { internalType : 'string' , name : '' , type : 'string' , } , ] , payable : false , stateMutability : 'pure' , type : 'function' , } , ] ; const VersionManagerABI = [ { constant : true , inputs : [ ] , name : 'version' , outputs : [ { internalType : 'string' , name : '' , type : 'string' , } , ] , payable : false , stateMutability : 'view' , type : 'function' , } , ] ; export async function getABI ( contractName , web3 ) { let versionManager = new web3 . eth . Contract ( VersionManagerABI , await getAddress ( 'versionManager' , web3 ) ) ; let protocolVersion = await versionManager . methods . version ( ) . call ( ) ; let versionMap = { } ; for ( let version of protocolVersions ) { versionMap [ version . replace ( 'v' , '' ) ] = SUPPORTED_ABIS [ version ] [ contractName ] ; } let abi = getAPIVersion ( versionMap , protocolVersion ) ; return abi ; } export async function getSDK < T extends SDK > ( sdk , ... args ) { let [ web3 ] = args ; let apiClass ; switch ( sdk ) { case 'Assets' : apiClass = Assets ; break ; case 'HubAuth' : apiClass = HubAuth ; break ; case 'LayerOneOracle' : apiClass = LayerOneOracle ; break ; case 'LayerTwoOracle' : apiClass = await resolveApiVersion ( layerTwoOracleMeta , web3 ) ; break ; case 'PrepaidCard' : apiClass = await resolveApiVersion ( prepaidCardMeta , web3 ) ; break ; case 'PrepaidCardMarket' : apiClass = await resolveApiVersion ( prepaidCardMarketMeta , web3 ) ; break ; case 'RevenuePool' : apiClass = await resolveApiVersion ( revenuePoolMeta , web3 ) ; break ; case 'RewardPool' : apiClass = await resolveApiVersion ( rewardPoolMeta , web3 ) ; break ; case 'RewardManager' : apiClass = await resolveApiVersion ( rewardManagerMeta , web3 ) ; break ; case 'Safes' : apiClass = Safes ; break ; case 'TokenBridgeForeignSide' : apiClass = TokenBridgeForeignSide ; break ; case 'TokenBridgeHomeSide' : apiClass = TokenBridgeHomeSide ; break ; default : assertNever ( sdk as never ) ; } return new apiClass ( ... args ) ; } async function resolveApiVersion ( meta , web3 ) { let contract = new web3 . eth . Contract ( cardPayVersionABI , await getAddress ( meta . contractName , web3 ) ) ; let protocolVersion = await contract . methods . cardpayVersion ( ) . call ( ) ; let versionMap = mapKeys ( meta . apiVersions , ( _ , key ) => key . replace ( 'v' , '' ) . replace ( /_/g , '.' ) ) ; let apiClass = getAPIVersion ( versionMap , protocolVersion ) ; return apiClass ; } interface APIVersionMap < T > { [ version ] : T ; } function getAPIVersion < T > ( apiVersionMap , protocolVersion ) { let availableApiVersions = Object . keys ( apiVersionMap ) . sort ( ) . reverse ( ) ; if ( protocolVersion === 'any' ) { return apiVersionMap [ availableApiVersions [ 0 ] ] ; } let satisfyingApiVersion ; for ( let possibleApiVersion of availableApiVersions ) { if ( satisfies ( protocolVersion , `~${ possibleApiVersion }` ) ) { satisfyingApiVersion = possibleApiVersion ; break ; } } if ( ! satisfyingApiVersion ) { throw new Error ( `Could not find a version of the API that satisfies cardpay protocol version ${ protocolVersion } for PrepaidCard` ) ; } return apiVersionMap [ satisfyingApiVersion ] ; } function assertNever ( _value ) { throw new Error ( `not never` ) ; }