import * as airnodeAbi from '@api3/airnode-abi' ; import { AirnodeRrp , RequesterAuthorizerWithAirnode } from '@api3/airnode-protocol' ; import { ethers } from 'ethers' ; const assertAllParamsAreReturned = ( params , ethersParams ) => { if ( Object . keys ( params ) . length !== ethersParams . length ) { throw new Error ( `SDK doesn't return some of the parameters!` ) ; } } ; param sponsorAddress returns export const deriveWalletPathFromSponsorAddress = ( sponsorAddress ) : string => { const sponsorAddressBN = ethers . BigNumber . from ( ethers . utils . getAddress ( sponsorAddress ) ) ; const paths = [ ] ; for ( let i = 0 ; i < 6 ; i ++ ) { const shiftedSponsorAddressBN = sponsorAddressBN . shr ( 31 * i ) ; paths . push ( shiftedSponsorAddressBN . mask ( 31 ) . toString ( ) ) ; } return `0/${ paths . join ( '/' ) }` ; } ; export const deriveAirnodeXpub = ( airnodeMnemonic ) : string => { const airnodeHdNode = ethers . utils . HDNode . fromMnemonic ( airnodeMnemonic ) . derivePath ( "m/44'/60'/0'" ) ; return airnodeHdNode . neuter ( ) . extendedKey ; } ; export const verifyAirnodeXpub = ( airnodeXpub , airnodeAddress ) : ethers . utils . HDNode => { const hdNode = ethers . utils . HDNode . fromExtendedKey ( airnodeXpub ) ; if ( airnodeAddress !== hdNode . derivePath ( '0/0' ) . address ) { throw new Error ( `xpub does not belong to Airnode: ${ airnodeAddress }` ) ; } return hdNode ; } ; export async function deriveSponsorWalletAddress ( airnodeXpub , airnodeAddress , sponsorAddress ) { const hdNode = verifyAirnodeXpub ( airnodeXpub , airnodeAddress ) ; const derivationPath = deriveWalletPathFromSponsorAddress ( sponsorAddress ) ; return hdNode . derivePath ( derivationPath ) . address ; } export async function sponsorRequester ( airnodeRrp , requesterAddress ) { await airnodeRrp . setSponsorshipStatus ( requesterAddress , true ) ; return requesterAddress ; } export async function unsponsorRequester ( airnodeRrp , requesterAddress ) { await airnodeRrp . setSponsorshipStatus ( requesterAddress , false ) ; return requesterAddress ; } export interface Template { parameters : string | airnodeAbi . InputParameter [ ] ; airnode : string ; endpointId : string ; } export async function createTemplate ( airnodeRrp , template ) { let encodedParameters ; if ( typeof template . parameters == 'string' ) { encodedParameters = template . parameters ; } else { encodedParameters = airnodeAbi . encode ( template . parameters ) ; } const tx = await airnodeRrp . createTemplate ( template . airnode , template . endpointId , encodedParameters ) ; return new Promise < string > ( ( resolve ) => airnodeRrp . provider . once ( tx . hash , ( { logs } ) => { const parsedLog = airnodeRrp . interface . parseLog ( logs [ 0 ] ) ; resolve ( parsedLog . args . templateId ) ; } ) ) ; } export async function requestWithdrawal ( airnodeRrp , airnodeAddress , sponsorWalletAddress ) { const tx = await airnodeRrp . requestWithdrawal ( airnodeAddress , sponsorWalletAddress ) ; return new Promise < string > ( ( resolve ) => airnodeRrp . provider . once ( tx . hash , ( { logs } ) => { const parsedLog = airnodeRrp . interface . parseLog ( logs [ 0 ] ) ; resolve ( parsedLog . args . withdrawalRequestId ) ; } ) ) ; } export async function checkWithdrawalRequest ( airnodeRrp , requestId ) { const filter = airnodeRrp . filters . FulfilledWithdrawal ( null , null , requestId , null , null ) ; const logs = await airnodeRrp . queryFilter ( filter ) ; if ( logs . length === 0 ) { return undefined ; } const ethersLogParams = logs [ 0 ] . args ; const { airnode , sponsor , withdrawalRequestId , sponsorWallet , amount } = ethersLogParams ; const logParams = { airnode , sponsor , withdrawalRequestId , sponsorWallet , amount } ; assertAllParamsAreReturned ( logParams , ethersLogParams ) ; return { ... logParams , amount : amount . toString ( ) } ; } export async function deriveEndpointId ( oisTitle , endpointName ) { return ethers . utils . keccak256 ( ethers . utils . defaultAbiCoder . encode ( [ 'string' , 'string' ] , [ oisTitle , endpointName ] ) ) ; } export async function requesterToRequestCountPlusOne ( airnodeRrp , requesterAddress ) { return ( await airnodeRrp . requesterToRequestCountPlusOne ( requesterAddress ) ) . toString ( ) ; } export async function getTemplate ( airnodeRrp , templateId ) { const ethersTemplate = await airnodeRrp . getTemplates ( [ templateId ] ) ; const { airnodes : [ airnode ] , endpointIds : [ endpointId ] , parameters : [ parameters ] , } = ethersTemplate ; const template = { airnode , endpointId , parameters } ; assertAllParamsAreReturned ( template , ethersTemplate ) ; return template ; } export async function getTemplates ( airnodeRrp , templateIds ) { const ethersTemplate = await airnodeRrp . getTemplates ( templateIds ) ; const { airnodes , endpointIds , parameters } = ethersTemplate ; const templates = { airnodes , endpointIds , parameters } ; assertAllParamsAreReturned ( templates , ethersTemplate ) ; const formattedTemplates = airnodes . map ( ( _ , i ) => ( { airnode : airnodes [ i ] , endpointId : endpointIds [ i ] , parameters : parameters [ i ] , } ) ) ; return formattedTemplates ; } export function sponsorToRequesterToSponsorshipStatus ( airnodeRrp , sponsorAddress , requesterAddress ) { return airnodeRrp . sponsorToRequesterToSponsorshipStatus ( sponsorAddress , requesterAddress ) ; } export async function sponsorToWithdrawalRequestCount ( airnodeRrp , sponsorAddress ) { const requestsCount = await airnodeRrp . sponsorToWithdrawalRequestCount ( sponsorAddress ) ; return requestsCount . toString ( ) ; } export interface FulfillWithdrawalReturnValue { airnode : string ; sponsor : string ; withdrawalRequestId : string ; sponsorWallet : string ; amount : string ; } export async function fulfillWithdrawal ( airnodeRrp , requestId , airnodeAddress , sponsorAddress , amount ) { const tx = await airnodeRrp . fulfillWithdrawal ( requestId , airnodeAddress , sponsorAddress , { value : ethers . utils . parseEther ( amount ) , } ) ; const filter = airnodeRrp . filters . FulfilledWithdrawal ( airnodeAddress , sponsorAddress , requestId , null , null ) ; return new Promise < FulfillWithdrawalReturnValue | null > ( ( resolve ) => airnodeRrp . once ( filter , ( airnode , sponsor , withdrawalRequestId , sponsorWallet , amount , event ) => { if ( event . transactionHash !== tx . hash ) { resolve ( null ) ; } resolve ( { airnode , sponsor , withdrawalRequestId , sponsorWallet , amount : amount . toString ( ) } ) ; } ) ) ; } export async function setWhitelistExpiration ( requesterAuthorizerWithAirnode , airnodeAddress , endpointId , requesterAddress , expirationTimestamp ) { const tx = await requesterAuthorizerWithAirnode . setWhitelistExpiration ( airnodeAddress , endpointId , requesterAddress , expirationTimestamp ) ; await tx . wait ( ) ; } export async function extendWhitelistExpiration ( requesterAuthorizerWithAirnode , airnodeAddress , endpointId , requesterAddress , expirationTimestamp ) { const tx = await requesterAuthorizerWithAirnode . extendWhitelistExpiration ( airnodeAddress , endpointId , requesterAddress , expirationTimestamp ) ; await tx . wait ( ) ; } export async function setIndefiniteWhitelistStatus ( requesterAuthorizerWithAirnode , airnodeAddress , endpointId , requesterAddress , status ) { const tx = await requesterAuthorizerWithAirnode . setIndefiniteWhitelistStatus ( airnodeAddress , endpointId , requesterAddress , status ) ; await tx . wait ( ) ; } export async function getWhitelistStatus ( requesterAuthorizerWithAirnode , airnodeAddress , endpointId , requesterAddress ) { const { expirationTimestamp , indefiniteWhitelistCount } = await requesterAuthorizerWithAirnode . airnodeToEndpointIdToRequesterToWhitelistStatus ( airnodeAddress , endpointId , requesterAddress ) ; return { expirationTimestamp : expirationTimestamp . toNumber ( ) , indefiniteWhitelistCount : indefiniteWhitelistCount . toNumber ( ) , } ; } export async function isRequesterWhitelisted ( requesterAuthorizerWithAirnode , airnodeAddress , endpointId , requesterAddress ) { return requesterAuthorizerWithAirnode . requesterIsWhitelisted ( airnodeAddress , endpointId , requesterAddress ) ; } export async function generateMnemonic ( ) { const wallet = ethers . Wallet . createRandom ( ) ; return wallet . mnemonic . phrase ; } export async function deriveAirnodeAddress ( airnodeMnemonic ) { return ethers . Wallet . fromMnemonic ( airnodeMnemonic ) . address ; }