import { Events, type IPortalApi, generateTraceId, sdkLogger, } from '@portal-hq/utils' import { ScanEVMRequest, ScanEVMResponse, ScanEip712Request, ScanEip712Response, ScanNftRequest, ScanNftResponse, ScanSolanaRequest, ScanSolanaResponse, ScanTokenRequest, ScanTokenResponse, ScanUrlRequest, ScanUrlResponse, ScreenAddressApiResponse, ScreenAddressRequest, } from './types' const HYPERNATIVE_BASE_PATH = '/api/v3/clients/me/integrations/hypernative' const HypernativeEndpoint = { evm: `${HYPERNATIVE_BASE_PATH}/evm/scan`, eip712: `${HYPERNATIVE_BASE_PATH}/eip-712/scan`, solana: `${HYPERNATIVE_BASE_PATH}/solana/scan`, addresses: `${HYPERNATIVE_BASE_PATH}/addresses/scan`, nfts: `${HYPERNATIVE_BASE_PATH}/nfts/scan`, tokens: `${HYPERNATIVE_BASE_PATH}/tokens/scan`, url: `${HYPERNATIVE_BASE_PATH}/url/scan`, } as const export interface IPortalHypernativeApi { scanEVMTx(params: ScanEVMRequest): Promise scanEip712Tx(params: ScanEip712Request): Promise scanSolanaTx(params: ScanSolanaRequest): Promise scanAddresses(params: ScreenAddressRequest): Promise scanNfts(params: ScanNftRequest): Promise scanTokens(params: ScanTokenRequest): Promise scanURL(params: ScanUrlRequest): Promise } export interface PortalHypernativeApiOptions { api: IPortalApi } export class PortalHypernativeApi implements IPortalHypernativeApi { private readonly api: IPortalApi constructor(options: PortalHypernativeApiOptions) { this.api = options.api } public async scanEVMTx(params: ScanEVMRequest): Promise { const path = HypernativeEndpoint.evm const body = params const response = await this.post(path, body) await this.trackEvent(Events.HypernativeScanTx, { path, type: 'evm', }) return response } public async scanEip712Tx( params: ScanEip712Request, ): Promise { const path = HypernativeEndpoint.eip712 const body = params const response = await this.post( path, body, ) await this.trackEvent(Events.HypernativeScanTx, { path, type: 'eip712', }) return response } public async scanSolanaTx( params: ScanSolanaRequest, ): Promise { const path = HypernativeEndpoint.solana const body = params const response = await this.post( path, body, ) await this.trackEvent(Events.HypernativeScanTx, { path, type: 'solana', }) return response } public async scanAddresses( params: ScreenAddressRequest, ): Promise { const path = HypernativeEndpoint.addresses const body = params const response = await this.post( path, body, ) await this.trackEvent(Events.HypernativeScanAddresses, { path, count: params.addresses.length, }) return response } public async scanNfts(params: ScanNftRequest): Promise { const path = HypernativeEndpoint.nfts const response = await this.post( path, params, ) await this.trackEvent(Events.HypernativeScanNFTs, { path, count: params.nfts.length, }) return response } public async scanTokens( params: ScanTokenRequest, ): Promise { const path = HypernativeEndpoint.tokens const response = await this.post( path, params, ) await this.trackEvent(Events.HypernativeScanTokens, { path, count: params.tokens.length, }) return response } public async scanURL(params: ScanUrlRequest): Promise { const path = HypernativeEndpoint.url const response = await this.post( path, params, ) await this.trackEvent(Events.HypernativeScanURL, { path, url: params.url, }) return response } private async post(path: string, body: B): Promise { return this.api.requests.post(path, { headers: { Authorization: `Bearer ${this.api.apiKey}`, Accept: 'application/json', 'Content-Type': 'application/json', }, body, traceId: generateTraceId(), }) } private async trackEvent( event: string, properties: Record, ): Promise { try { await this.api.track(event, properties) } catch (error) { sdkLogger.warn( `[PortalHypernativeApi] Failed to track event "${event}":`, error, ) } } } export default PortalHypernativeApi