@ixily/activ
Version:
Alpha Capture Trade Idea Verification. Blockchain ownership proven trade ideas and strategies.
463 lines (410 loc) • 11 kB
text/typescript
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,
},
}