import { ErrorResponse } from "@walletconnect/jsonrpc-types" ; import { AppMetadata , BlockchainTypes , JsonRpcPermissions , NotificationPermissions , SequenceTypes , PairingTypes , SessionTypes , Validation , SignalTypes , StoreEvent , } from "@walletconnect/types" ; import { ERROR } from "./error" ; export function isSignalTypePairing ( signal ) { return signal . method === "pairing" ; } export function isSignalTypeUri ( signal ) { return signal . method === "uri" ; } export function isSequenceRespondedStatus ( status ) { return status === "responded" ; } export function isSequenceResponded ( pending ) { return isSequenceRespondedStatus ( pending . status ) && "outcome" in pending ; } export function isSequenceRejected ( response ) { return "reason" in response ; } export function isSequenceFailed ( outcome ) { return "reason" in outcome ; } export function isPairingRespondedStatus ( status ) { return status === "responded" ; } export function isPairingResponded ( pending ) { return isPairingRespondedStatus ( pending . status ) && "outcome" in pending ; } export function isPairingRejected ( response ) { return "reason" in response ; } export function isPairingFailed ( outcome ) { return "reason" in outcome ; } export function isSessionRespondedStatus ( status ) { return status === "responded" ; } export function isSessionResponded ( pending ) { return isPairingRespondedStatus ( pending . status ) && "outcome" in pending ; } export function isSessionRejected ( response ) { return "reason" in response ; } export function isSessionFailed ( outcome ) { return "reason" in outcome ; } export function isStoreUpdatedEvent < T = any > ( event ) { return "update" in event ; } export function validateSessionProposeParamsPermissions ( permissions ) { const blockchainPermissionsValidation = validateBlockchainPermissions ( permissions . blockchain ) ; if ( isValidationInvalid ( blockchainPermissionsValidation ) ) { return blockchainPermissionsValidation ; } const jsonRpcPermissionsValidation = validateJsonRpcPermissions ( permissions . jsonrpc ) ; if ( isValidationInvalid ( jsonRpcPermissionsValidation ) ) { return jsonRpcPermissionsValidation ; } const notificationPermissionsValidation = validateNotificationPermissions ( permissions . notifications ) ; if ( isValidationInvalid ( notificationPermissionsValidation ) ) { return notificationPermissionsValidation ; } return formatValidResult ( ) ; } export function validateSessionProposeParamsMetadata ( metadata ) { if ( ! isValidString ( metadata . name ) ) { return formatInvalidResult ( ERROR . MISSING_OR_INVALID . format ( { name : "metadata name" } ) ) ; } if ( ! isValidString ( metadata . description ) ) { return formatInvalidResult ( ERROR . MISSING_OR_INVALID . format ( { name : "metadata description" } ) ) ; } if ( typeof metadata . url === "undefined" || ! isValidUrl ( metadata . url ) ) { return formatInvalidResult ( ERROR . MISSING_OR_INVALID . format ( { name : "metadata url" } ) ) ; } if ( typeof metadata . icons === "undefined" || ! isValidArray ( metadata . icons , isValidUrl ) ) { return formatInvalidResult ( ERROR . MISSING_OR_INVALID . format ( { name : "metadata icons" } ) ) ; } return formatValidResult ( ) ; } export function validateSessionProposeParams ( params ) { const permissionsValidation = validateSessionProposeParamsPermissions ( params . permissions ) ; if ( isValidationInvalid ( permissionsValidation ) ) { return permissionsValidation ; } const metadataValidation = validateSessionProposeParamsMetadata ( params . metadata ) ; if ( isValidationInvalid ( metadataValidation ) ) { return metadataValidation ; } return formatValidResult ( ) ; } export function validateSessionRespondParams ( params ) { if ( params . approved ) { if ( typeof params . response === "undefined" ) { return formatInvalidResult ( ERROR . MISSING_RESPONSE . format ( { context : "session" } ) ) ; } const stateValidation = validateBlockchainState ( params . response . state , params . proposal . permissions . blockchain ) ; if ( isValidationInvalid ( stateValidation ) ) { return stateValidation ; } const metadataValidation = validateSessionProposeParamsMetadata ( params . response . metadata ) ; if ( isValidationInvalid ( metadataValidation ) ) { return metadataValidation ; } } return formatValidResult ( ) ; } export function validateBlockchainPermissions ( blockchain ? ) { if ( typeof blockchain === "undefined" || typeof blockchain . chains === "undefined" || ! isValidArray ( blockchain . chains , isValidChainId ) ) { return formatInvalidResult ( ERROR . MISSING_OR_INVALID . format ( { name : "blockchain permissions" } ) ) ; } return formatValidResult ( ) ; } export function validateJsonRpcPermissions ( jsonrpc ? ) { if ( typeof jsonrpc === "undefined" || typeof jsonrpc . methods === "undefined" || ! isValidArray ( jsonrpc . methods , isValidString ) ) { return formatInvalidResult ( ERROR . MISSING_OR_INVALID . format ( { name : "jsonrpc permissions" } ) ) ; } return formatValidResult ( ) ; } export function validateNotificationPermissions ( notifications ) { if ( typeof notifications === "undefined" || typeof notifications . types === "undefined" || ! isValidArray ( notifications . types , isValidString ) ) { return formatInvalidResult ( ERROR . MISSING_OR_INVALID . format ( { name : "notification permissions" } ) ) ; } return formatValidResult ( ) ; } export function validateBlockchainState ( state ? , blockchain ? ) { if ( typeof blockchain === "undefined" || typeof blockchain . chains === "undefined" || ! isValidArray ( blockchain . chains , isValidChainId ) ) { return formatInvalidResult ( ERROR . MISSING_OR_INVALID . format ( { name : "blockchain permissions" } ) ) ; } if ( typeof state === "undefined" || typeof state . accounts === "undefined" || ! isValidArray ( state . accounts , isValidAccountId ) ) { return formatInvalidResult ( ERROR . MISSING_OR_INVALID . format ( { name : "state accounts" } ) ) ; } const mismatched = state . accounts . filter ( accountId => { const [ namespace , reference ] = accountId . split ( ":" ) ; const chainId = `${ namespace }:${ reference }` ; return ! blockchain . chains . includes ( chainId ) ; } ) ; if ( mismatched . length ) { return formatInvalidResult ( ERROR . MISMATCHED_ACCOUNTS . format ( { mismatched } ) ) ; } return formatValidResult ( ) ; } export function isValidArray ( arr , itemCondition ? ) { if ( Array . isArray ( arr ) ) { if ( typeof itemCondition !== "undefined" && arr . length ) { const matches = arr . filter ( itemCondition ) ; return matches . length === arr . length ; } else { return true ; } } return false ; } export function isValidString ( value ) { return typeof value === "string" && ! ! value . trim ( ) ; } export function isValidChainId ( value ) { if ( isValidString ( value ) && value . includes ( ":" ) ) { const split = value . split ( ":" ) ; return split . length === 2 ; } return false ; } export function isValidAccountId ( value ) { if ( isValidString ( value ) && value . includes ( ":" ) ) { const split = value . split ( ":" ) ; if ( split . length === 3 ) { const chainId = split [ 0 ] + ":" + split [ 1 ] ; return ! ! split [ 2 ] && isValidChainId ( chainId ) ; } } return false ; } export function isValidUrl ( value ) { if ( isValidString ( value ) ) { try { const url = new URL ( value ) ; return typeof url !== "undefined" ; } catch ( e ) { return false ; } } return false ; } export function isValidationInvalid ( validation ) { return ( "valid" in validation && validation . valid === false && "error" in validation && typeof validation . error . code === "number" && typeof validation . error . message === "string" ) ; } export function formatValidResult ( ) { return { valid : true } ; } export function formatInvalidResult ( error ) { return { valid : false , error } ; }