UNPKG

@ixily/activ

Version:

Alpha Capture Trade Idea Verification. Blockchain ownership proven trade ideas and strategies.

463 lines (410 loc) 11 kB
import pinataSDK from '@pinata/sdk' import 'isomorphic-fetch' import { Readable } from 'stream' import { CompressorModule, getBoolean, id, isUrl, LogModule as log, loop, rest, } from '../../' interface IPinataCreds { pinataApi: string pinataSecret: string } const state = { nftStorageKey: undefined as string | undefined, mockNftStorage: false as boolean, mockContents: new Map<string, string>(), ipfsProxyEnabled: false as boolean, usePinata: undefined as IPinataCreds | undefined, pinata: undefined as pinataSDK | undefined, } const inflateStr = async <T>(dt: T): Promise<T> => { if (typeof dt !== 'string') return dt return CompressorModule.inflate(dt) as T } const deflateStr = async <T>(dt: T): Promise<T> => { if (typeof dt !== 'string') return dt return CompressorModule.deflate(dt) as T } const getIpfsURLByCid = (cid: string) => { let url = 'https://ipfs.io/ipfs/' + cid if (!state.mockNftStorage) { try { if (state?.ipfsProxyEnabled) { url = `https://${cid}.ipfs.nftstorage.link` } } catch (err) { log.dev('getIpfsURL (error)', err) } } return url } const getIpfsURLByOriginalUrl = (url: string) => { if (state.mockNftStorage) { return 'https://ipfs.io/ipfs/' + url } else { try { // check if the url include .ipfs.nftstorage.link if ( state.ipfsProxyEnabled && !url.includes('.ipfs.nftstorage.link') && state.pinata === undefined ) { const splitUrl = url.split('https://ipfs.io/ipfs/') const cid = splitUrl[1] url = `https://${cid}.ipfs.nftstorage.link` } } catch (err) { log.dev('getIpfsURL (error)', err) } return url } } export const getIpfsURL = (value: string): string => { const urlCheck = isUrl(value) log.dev('getIpfsURL (urlCheck)', urlCheck) let response = null // console.log('urlCheck') // console.log(urlCheck) if (urlCheck) { // console.log('value') // console.log(value) response = getIpfsURLByOriginalUrl(value) // console.log('response') // console.log(response) } else { // console.log('value') // console.log(value) response = getIpfsURLByCid(value) // console.log('response') // console.log(response) } // log.dev('getIpfsURL (response)', response) return response } export const getIpfsURLPinata = (cid: string): string => { return `https://gateway.pinata.cloud/ipfs/${cid}` } const config = (_config: { nftStorageKey?: string mockNftStorage?: boolean ipfsProxyEnabled?: boolean usePinata?: IPinataCreds }) => { if (_config.nftStorageKey) { state.nftStorageKey = _config.nftStorageKey } if (_config.mockNftStorage !== undefined) { state.mockNftStorage = _config.mockNftStorage } if (_config.ipfsProxyEnabled !== undefined) { state.ipfsProxyEnabled = _config.ipfsProxyEnabled } if (state.mockNftStorage) { loadMockIpfsIdLitActions() } if (_config.usePinata) { state.usePinata = _config.usePinata } } const loadMockIpfsIdLitActions = () => { // addMockedIpfsId( // LIT_ACTIONS.GET_PRICE_BINANCE_V2.ipfsId, // LIT_ACTIONS.GET_PRICE_BINANCE_V2_CODE, // ) // addMockedIpfsId( // LIT_ACTIONS.GET_PRICE_BINANCE.fetcher.ipfsId, // LIT_ACTIONS.GET_PRICE_BINANCE_FETCHER_CODE, // ) // addMockedIpfsId( // LIT_ACTIONS.GET_PRICE_BINANCE.keyBearer.ipfsId, // LIT_ACTIONS.GET_PRICE_BINANCE_KEY_BEARER_CODE, // ) // addMockedIpfsId( // LIT_ACTIONS.GET_PRICE_BINANCE.provider.ipfsId, // LIT_ACTIONS.GET_PRICE_BINANCE_PROVIDER_CODE, // ) // addMockedIpfsId( // LIT_ACTIONS.GET_PRICE_BINANCE.verifier.ipfsId, // LIT_ACTIONS.GET_PRICE_BINANCE_VERIFIER_CODE, // ) // addMockedIpfsId( // LIT_ACTIONS.GET_PRICE_IEX_V1.ipfsId, // LIT_ACTIONS.GET_PRICE_IEX_V1_CODE, // ) } const addMockedIpfsId = (ipfsId: string, jsonContent: string) => { const url = 'https://ipfs.io/ipfs/' + ipfsId state.mockContents.set(url, jsonContent) } const assureClient = () => { if (state.nftStorageKey === undefined) { throw new Error('nft-storage client not configured') } // Add Pinata Client if (state.usePinata !== undefined && state.pinata === undefined) { state.pinata = new pinataSDK( state.usePinata.pinataApi, state.usePinata.pinataSecret, ) } } const nftStorageUploadviaAPI = async ( jsonMetadata: string, ): Promise<{ cid: string }> => { const request = await fetch('https://api.nft.storage/upload', { method: 'POST', headers: { Authorization: `Bearer ${state.nftStorageKey}`, }, body: jsonMetadata, }) const response = await request.json() log.dev('nftStorageUploadviaAPI (response)', response) if (response.ok !== true) { throw new Error('nft-storage upload error: ' + response.error.message) } const cid = response.value.cid if (cid === undefined || cid === null) { throw new Error('nft-storage upload error: cid is undefined or null') } return { cid, } } const storeJsonContent = async ( jsonContent: string, ): Promise<{ cid: string url: string }> => { // log.dev('jsonContent', jsonContent) if (state.mockNftStorage) { const cid = id() log.dev('cid', cid) const url = 'https://ipfs.io/ipfs/' + cid // log.dev('url', url) // log.dev('jsonContent', jsonContent) state.mockContents.set(url, jsonContent) log.dev('state.mockContents.get(url):') log.dev(state.mockContents.get(url)) // log.dev('state.mockContents.get(mock_url_+cid)') // log.dev(state.mockContents.get('https://ipfs.io/ipfs/' + cid)) log.dev('delivered url: ', url) return { cid, url, } } else { assureClient() jsonContent = await deflateStr(jsonContent) if (state.usePinata !== undefined) { const buffer = Buffer.from(jsonContent, 'utf8') const stream = Readable.from(buffer) // @ts-ignore stream.path = 'string.txt' const res = await state .pinata!.pinFileToIPFS(stream, { pinataMetadata: { name: 'AlphaCapture Pin Software' }, }) .catch((e) => { console.log(e) throw new Error('Failed to upload to pinata') }) const ans = { cid: res.IpfsHash, url: getIpfsURLPinata(res.IpfsHash), } // console.log('ans') // console.log(ans) /* await rest(2000) const contentCheck = await getJsonContent(ans.url) console.log('contentCheck') console.log(contentCheck) console.log('_+__+_+_+_+_+_+_+_+_+_+_++_') const contentCheckByCid = await getJsonContent(ans.cid) console.log('p----------------------------------') console.log('contentCheckByCid') console.log(contentCheckByCid) */ return ans } else { const response = await nftStorageUploadviaAPI(jsonContent) log.dev('storeJsonContent (response)', response) return { cid: response?.cid, url: getIpfsURL(response?.cid), } } } } const getJsonContent = async ( url: string, settings?: { forceIPFSdirectly?: boolean }, ): Promise<string> => { if (state.mockNftStorage) { return state.mockContents.get(url)! } else { // NOTE: the old function is causing the error ---> 429 Too Many Requests // we don't use a while to do it, we use a loop function and retry using a specific time and timeout let result: any = null if (getBoolean(!settings?.forceIPFSdirectly)) { url = getIpfsURL(url) // console.log('url') // console.log(url) } log.dev('getJsonContent (url)', url) const upToThreeHundredRandom = (): number => { return Math.floor(Math.random() * 300) } const fetchIpfsStore = async () => { const MaxTries = 15 let tries = 0 let got: boolean = false while (!got && tries < MaxTries) { try { // console.log('try') // console.log('url') // console.log(url) tries++ result = await fetch(url) got = true } catch (err: any) { // console.log('err') // console.log(err) // console.log('err.message') // console.log(err.message) // console.log('err.cause.code') // console.log(err.cause.code) if (typeof err.message === 'string') { if ( err.message.indexOf( 'failed, reason: connect ECONNREFUSED', ) !== -1 ) { log.prod('getJsonContent (error)', err) log.prod('getJsonContent (error) - retrying...') await rest(50 + upToThreeHundredRandom()) } else if ( err.cause?.code === 'ECONNREFUSED' || err.cause?.code === 'UND_ERR_CONNECT_TIMEOUT' || err.cause?.code === 'ECONNRESET' ) { log.prod('getJsonContent (error)', err) log.prod('getJsonContent (error) - retrying...') await rest(50 + upToThreeHundredRandom()) } else { throw err } } else { throw err } } } } const fetchPinata = async () => { const url2 = 'https://gateway.pinata.cloud/ipfs/' + url.substring(8, url.length - 21) // .ipfs.nftstorage.link const MaxTries = 15 let tries = 0 let got: boolean = false while (!got && tries < MaxTries) { try { // console.log('try pinata') // console.log('url2') // console.log(url2) tries++ result = await fetch(url2) got = true } catch (err: any) { // console.log('err') // console.log(err) // console.log('err.message') // console.log(err.message) // console.log('err.cause.code') // console.log(err.cause.code) if (typeof err.message === 'string') { if ( err.message.indexOf( 'failed, reason: connect ECONNREFUSED', ) !== -1 ) { log.prod('getJsonContent (error)', err) log.prod('getJsonContent (error) - retrying...') await rest(50 + upToThreeHundredRandom()) } else if ( err.cause?.code === 'ECONNREFUSED' || err.cause?.code === 'UND_ERR_CONNECT_TIMEOUT' || err.cause?.code === 'ECONNRESET' ) { log.prod('getJsonContent (error)', err) log.prod('getJsonContent (error) - retrying...') await rest(50 + upToThreeHundredRandom()) } else { throw err } } else { throw err } } } } const fetches = [fetchIpfsStore()] if (url.indexOf('.ipfs.nftstorage.link') !== -1) { fetches.push(fetchPinata()) } await Promise.race(fetches) if (result?.status === 200) { const jsonContent = await result.text() result = jsonContent log.dev(`getJsonContent (${url}) - ¡success!`) } else { await loop( async () => { const jsonContent = await result.text() result = jsonContent log.dev(`getJsonContent (${url}) - ¡success!`) }, async () => { let isPassed = false try { result = await fetch(url) if (result.status === 200) { isPassed = true } } catch (e: any) { isPassed = false log.dev(`getJsonContent (${url}) - retying...`) } return inflateStr(isPassed) }, { loopTimeInMs: 10000, limitTimeSecond: 24000, }, async (err: any) => { log.dev('err', err) }, ) } return inflateStr(result) } } export const NftStoreModule = { storeJsonContent, getJsonContent, config, utils: { getIpfsURL, }, }