UNPKG

@ixily/activ

Version:

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

712 lines (638 loc) 17.4 kB
import { ContractModule, IChain, id, ILitProvider, LogModule as log, NftStoreModule, rest, } from '../..' // import { ALL_LIT_CHAINS, LIT_CHAINS } from '@lit-protocol/constants' interface MyContractClients { chain: IChain contractAddress: string encryptionClient: any actionsClient: any } const MAX_LIT_ENC_DEC_ATTEMPTS = 5 const state = { litProvider: undefined as ILitProvider | undefined, isBrowser: false as boolean, contractAddress: '' as string, chain: 'mainnet' as IChain, litChainNaming: 'ethereum' as string, mock: false as boolean, mockActually: false as boolean, updating: false as boolean, contractClients: new Map<string, MyContractClients>(), gettingAuth: false as boolean, } const litNamedChain = (chain: IChain): string => { // console.log('_+_+_+_+_+_+_+_+_+_+_+_+__+') // console.log('LIST OF ALL SUPPORTED CHAINS:') // console.log(ALL_LIT_CHAINS) // console.log('LIT CHAINS:') // console.log(LIT_CHAINS) // console.log('_+_+_+_+_+_+_+_+_+_+_+_+__+') if ((chain as unknown as string) === 'mainnet') { return 'ethereum' } return chain } const config = async (_config: { litProvider: ILitProvider mock?: boolean }) => { state.litProvider = _config.litProvider state.isBrowser = _config.litProvider.isBrowser if (_config.mock !== undefined) { state.mock = _config.mock } ContractModule.getUpdatedStream().subscribe(() => { updateConfig() }) await updateConfig() } const updateConfig = async () => { while (state.updating) { await rest(20) } state.updating = true const contract = ContractModule.getBlockchainContract() state.chain = contract.recipe.chain state.litChainNaming = litNamedChain(state.chain) state.contractAddress = contract.recipe.coreContractAddress state.mockActually = state.mock if ((state.chain as unknown as string) === 'hardhat') { state.mockActually = true } if (!state.mockActually) { if (state.contractClients.get(state.contractAddress) === undefined) { const encryptionClient = await state.litProvider!.getEncryptionClient() const actionsClient = await state.litProvider!.getActionsClient() state.contractClients.set(state.contractAddress, { chain: state.chain, contractAddress: state.contractAddress, encryptionClient, actionsClient, }) } } state.updating = false } const getEncryptionClient = async (): Promise<any> => { while (state.contractClients.get(state.contractAddress) === undefined) { await rest(10) } return state.contractClients.get(state.contractAddress)!.encryptionClient } const getActionsClient = async (): Promise<any> => { while (state.contractClients.get(state.contractAddress) === undefined) { await rest(10) } return state.contractClients.get(state.contractAddress)!.actionsClient } const setContract = (contractAddress: string) => { state.contractAddress = contractAddress } const accessConditionsOwnId = (tokenId: number): any[] => { log.dev('state.chain') log.dev(state.chain) log.dev('tokenId') log.dev(tokenId) const tokenIdStr = tokenId.toString() const accessControlConditions = [ { contractAddress: state.contractAddress, standardContractType: 'ERC1155', method: 'balanceOf', parameters: [':userAddress', tokenIdStr], returnValueTest: { comparator: '>', value: '0', }, chain: state.litChainNaming, }, ] return accessControlConditions } const accessConditionsTemporary = (): any[] => { const accessControlConditions = [ { contractAddress: state.contractAddress, standardContractType: 'ERC1155', method: 'balanceOf', parameters: [':userAddress', '0'], returnValueTest: { comparator: '>', value: '0', }, chain: state.litChainNaming, }, ] return accessControlConditions } const recoverPublicIdeaKeyFromLitForNftId = async ( base64EncryptedString: string, encryptedSymmetricKey: string, tokenId: number, isPublic?: boolean, // chainToGoBack: IChain, ): Promise<string> => { if (state.mockActually || isPublic) return base64EncryptedString await updating() await getAuthSig() // log.dev( // 'recoverPublicIdeaKeyFromLitForNftId (base64EncryptedString)', // base64EncryptedString, // ) // log.dev( // 'recoverPublicIdeaKeyFromLitForNftId (encryptedSymmetricKey)', // encryptedSymmetricKey, // ) // log.dev('recoverPublicIdeaKeyFromLitForNftId (tokenId)', tokenId) let data: any let accessControlConditions: any[] // first we try as it was made public accessControlConditions = accessConditionsOwnId(tokenId) // console.log('accessControlConditions') // console.log(accessControlConditions) // log.dev( // 'recoverPublicIdeaKeyFromLitForNftId (accessControlConditions)', // accessControlConditions, // ) // if (state.networkEnv !== 'local') { // await makeSureChainMatches(state.networkEnv) // } let attempts: number = 0 while (true) { try { attempts++ data = await state.litProvider!.recoverString( await getEncryptionClient(), base64EncryptedString, encryptedSymmetricKey, accessControlConditions, state.litChainNaming, ) break } catch (err: any) { if ( err.message.indexOf( 'The access control condition check failed. Are you sure you meet the conditions?', ) !== -1 ) { throw err } if ( err.message.indexOf( 'The access control conditions you passed in do not match the ones that were set by the condition creator for this encryptedSymmetricKey.', ) !== -1 ) { throw err } // 'The access control conditions you passed in do not match the ones that were set by the condition creator for this encryptedSymmetricKey.' if (attempts > MAX_LIT_ENC_DEC_ATTEMPTS) { throw err } await rest(200) } } // await makeSureChainMatches(chainToGoBack) // log.dev('recoverPublicIdeaKeyFromLitForNftId (data)', data) return data } const AUTH_SIG_EXPIRATION = 30 * 1000 // 30 seconds const getAuthSig = async (/*chainToGoBack: IChain*/): Promise<any> => { if (state.mockActually) return id() await updating() while (state.gettingAuth) { await rest(200) } state.gettingAuth = true // TODO => Fix actually right authSign on Lit Provider to match latest selected wallet const result = await state.litProvider!.getAuthSig(state.litChainNaming) state.gettingAuth = false return result } const storePublicIdeaKeyOnLitForNftId = async ( nftId: number, ideaString: string, isPublic?: boolean, // chainToGoBack: IChain, ): Promise<{ encryptedPublicKey: string; encryptedIdea: string }> => { if (state.mockActually || isPublic) return { encryptedPublicKey: '' + nftId, encryptedIdea: ideaString } await updating() await getAuthSig() // log.dev('storePublicIdeaKeyOnLitForNftId (nftId)', nftId) // log.dev('storePublicIdeaKeyOnLitForNftId (ideaString)', ideaString) const accessControlConditions = accessConditionsOwnId(nftId) // log.dev( // 'storePublicIdeaKeyOnLitForNftId (accessControlConditions)', // accessControlConditions, // ) // if (state.networkEnv !== 'local') { // await makeSureChainMatches(state.networkEnv) // } const { encryptedString, symmetricKey, authSig } = await state.litProvider!.encryptString(ideaString, state.litChainNaming) // log.dev( // 'storePublicIdeaKeyOnLitForNftId (encryptedString)', // encryptedString, // ) // log.dev('storePublicIdeaKeyOnLitForNftId (symmetricKey)', symmetricKey) // log.dev('storePublicIdeaKeyOnLitForNftId (authSig)', authSig) const encryptedSymmetricKey = await state.litProvider!.saveKey( await getEncryptionClient(), symmetricKey, accessControlConditions, authSig, state.litChainNaming, ) // await makeSureChainMatches(chainToGoBack) // log.dev( // 'storePublicIdeaKeyOnLitForNftId (encryptedSymmetricKey)', // encryptedSymmetricKey.encryptedSymmetricKeyString, // ) const obj = { encryptedPublicKey: encryptedSymmetricKey.encryptedSymmetricKeyString, encryptedIdea: encryptedString, } // log.dev('storePublicIdeaKeyOnLitForNftId (obj)', obj) return obj } const storeTemporaryPublicIdeaKeyOnLit = async ( ideaString: string, isPublic?: boolean, // chainToGoBack: IChain, ): Promise<{ encryptedPublicKey: string encryptedSymetricKeyRaw: string symmetricKey: string encryptedIdea: string authSig: any }> => { if (state.mockActually || isPublic) { const rId = id() return { encryptedPublicKey: rId, encryptedSymetricKeyRaw: rId, symmetricKey: rId, encryptedIdea: ideaString, authSig: rId, } } await updating() await getAuthSig() // log.dev('storePublicIdeaKeyOnLitForNftId (ideaString)', ideaString) const accessControlConditions = accessConditionsTemporary() // log.dev( // 'storePublicIdeaKeyOnLitForNftId (accessControlConditions)', // accessControlConditions, // ) // if (state.networkEnv !== 'local') { // await makeSureChainMatches(state.networkEnv) // } const { encryptedString, symmetricKey, authSig } = await state.litProvider!.encryptString(ideaString, state.litChainNaming) // log.dev( // 'storePublicIdeaKeyOnLitForNftId (encryptedString)', // encryptedString, // ) // log.dev('storePublicIdeaKeyOnLitForNftId (symmetricKey)', symmetricKey) // log.dev('storePublicIdeaKeyOnLitForNftId (authSig)', authSig) const saveKeyData = await state.litProvider!.saveKey( await getEncryptionClient(), symmetricKey, accessControlConditions, authSig, state.litChainNaming, false, // permanent: false, ) // await makeSureChainMatches(chainToGoBack) // log.dev( // 'storePublicIdeaKeyOnLitForNftId (encryptedSymmetricKey)', // saveKeyData.encryptedSymmetricKeyString, // ) const obj = { symmetricKey, encryptedPublicKey: saveKeyData.encryptedSymmetricKeyString, encryptedSymetricKeyRaw: saveKeyData.encryptedSymmetricKey, encryptedIdea: encryptedString, authSig, } // log.dev('storePublicIdeaKeyOnLitForNftId (obj)', obj) return obj } const updateToDefinitiveAccessControlConditions = async ( encryptedSymmetricKey: string, symmetricKey: string, nftId: number, authSig: any, isPublic?: boolean, ) => { // log.dev( // 'updateToDefinitiveAccessControlConditions (state.mock)', // state.mock, // ) if (state.mock || isPublic) return await updating() await getAuthSig() // log.dev( // 'updateToDefinitiveAccessControlConditions (symmetricKey)', // symmetricKey, // ) const accessControlConditions = accessConditionsOwnId(nftId) // log.dev( // 'updateToDefinitiveAccessControlConditions (accessControlConditions)', // accessControlConditions, // ) // log.dev('updateToDefinitiveAccessControlConditions (authSig)', authSig) // if (state.networkEnv !== 'local') { // await makeSureChainMatches(state.networkEnv) // } let attempts: number = 0 const updtACC = async () => { // authSig = await getAuthSig() await state.litProvider!.updateConditionsKey( await getEncryptionClient(), encryptedSymmetricKey, symmetricKey, accessControlConditions, authSig, state.litChainNaming, true, ) } while (true) { try { attempts++ await updtACC() break } catch (e) { console.log( 'LitModule: Error on updateToDefinitiveAccessControlConditions', ) // 'The access control conditions you passed in do not match the ones that were set by the condition creator for this encryptedSymmetricKey.' if (attempts > MAX_LIT_ENC_DEC_ATTEMPTS) { throw e } await rest(500) } } // await makeSureChainMatches(chainToGoBack) } /* export const runJSFallback = async <T>( javascriptCode: string, params: any, ): Promise<{ response: T }> => { if (state.mock) return runJSFallbackMock<T>(javascriptCode, params) // if (state.networkEnv !== 'local' && state.networkEnv !== chainToGoBack) { // await makeSureChainMatches(state.networkEnv) // } const litActionResponse = await state.litProvider!.runJSFallback<T>( javascriptCode, params, state.litChainNaming, ) // await makeSureChainMatches(chainToGoBack) // log.dev('runJS (litActionResponse)', litActionResponse) // your global sign here... return litActionResponse } */ // testId => 105513016513708266538432932353309329163187878127577176348882795059994013308295 // testEth => 0x2c0b39760f91F60f1777F8269227Fc9A073a1659 // testPubKey => 0x04386cab00b0cbe7da91e445a1f305d84d1017d974f6316f8c397c36ff5d07a688a7ed1c737ea9b615b462d3909e2aa52cf48ee6318f6284cc94a96822d43d2333 const testJS = async (): Promise<{ results: Array<{ result: 'success' | 'failure' nodes: number response?: any error?: any }> success: boolean minForSuccess: number maximumNodes: number workingNodes: number }> => { await updating() const ipfsId = 'QmSCxGRRznNDJRDri9qd3batstNiSj9xDHRTVhj8j2TKfo' const publicKey = '0x04386cab00b0cbe7da91e445a1f305d84d1017d974f6316f8c397c36ff5d07a688a7ed1c737ea9b615b462d3909e2aa52cf48ee6318f6284cc94a96822d43d2333' const results: Array<{ result: 'success' | 'failure' nodes: number response?: any error?: any }> = [] const maximumNodes = 10 const minForSuccess = 7 let nodes: number = maximumNodes const genResultForNodes = async (nodes: number) => { return runJS(ipfsId, publicKey, undefined, nodes) .then((response) => { return { result: 'success' as 'success', nodes, response, } }) .catch((error) => { return { result: 'failure' as 'failure', nodes, error, } }) } results.push(await genResultForNodes(maximumNodes)) while (results[results.length - 1].result === 'failure' && nodes > 0) { nodes-- results.push(await genResultForNodes(nodes)) } const finalResult = { results, success: nodes >= minForSuccess, minForSuccess, maximumNodes, workingNodes: nodes, } return finalResult } export const runJS = async ( ipfsId: string, publicKey: string, params?: any, nodes: number = 10, ): Promise<any> => { // console.log('state.mock:') // console.log(state.mock) if (state.mock) return runJSMock(ipfsId, publicKey, params) await updating() await getAuthSig() // if (state.networkEnv !== 'local' && state.networkEnv !== chainToGoBack) { // await makeSureChainMatches(state.networkEnv) // } // log.dev('Lit Module: runJS: ipfsId: ', ipfsId) // log.dev('Lit Module: runJS: publicKey: ', publicKey) // log.dev('Lit Module: runJS: nodes: ', nodes) const litActionResponse = await state.litProvider!.runJS( await getActionsClient(), ipfsId, publicKey, state.litChainNaming, params, nodes, ) // await makeSureChainMatches(chainToGoBack) // log.dev('runJS (litActionResponse)', litActionResponse) // your global sign here... return litActionResponse } const runJSFallbackMock = async <T>( javascriptCode: string, params: any, ): Promise<{ response: T }> => { let addParams = '' for (const param in params) { addParams += `let ${param} = ${ params[param] === undefined ? 'undefined' : typeof params[param] === 'string' ? `'${params[param]}'` : typeof params[param] === 'object' ? JSON.stringify(params[param]) : params[param] }; ` } const masterFunctionStart = (state.isBrowser ? '' : `const fetch = require('isomorphic-fetch'); `) + ` const ethers = { utils: { toUtf8Bytes: (value) => { return value }, keccak256: (value) => { return value } } } async function masterFunction() { let resolvedMaster = false; let state = { response: null, signatures: {} } const LitActions = { setResponse: (response) => { state = { ...state, ...response } resolvedMaster = true }, ethPersonalSignMessageEcdsa: ( message, publicKey, sigName, ) => { state.signatures = {} } } const asyncCalledFunction = async () => { ` const masterFunctionEnd = ` } let error = undefined asyncCalledFunction().catch((e) => { error = e }) while(!resolvedMaster && error === undefined ) { console.log('error', error) await new Promise((resolve) => setTimeout(resolve, 1000)) } if(error !== undefined) { throw error } return state; } masterFunction() ` const code = masterFunctionStart + addParams + javascriptCode.replace('go()', 'await go()') + masterFunctionEnd const codeEscaped = code.replace(/'\n'/g, "'\\n'") try { // console.log('what is going on?') // console.log(codeEscaped) const resultRaw = await eval(codeEscaped) const result = resultRaw as { response: string } log.dev('result:') log.dev(result) const resultResponse = { ...result, response: JSON.parse(result.response) as T, } return resultResponse } catch (e) { log.dev('Error on mock lit action:') log.dev(e) throw e } } const runJSMock = async <T>( ipfsId: string, publicKey: string, params: any, ): Promise<{ signatures: any response: T logs: string[] }> => { log.dev('https://ipfs.io/ipfs/' + ipfsId) const url = 'https://ipfs.io/ipfs/' + ipfsId const codeString = await NftStoreModule.getJsonContent(url, { forceIPFSdirectly: true, }) log.dev('codeString:') log.dev(codeString) params['publicKey'] = publicKey const responseResult = await runJSFallbackMock<T>(codeString, params) return { ...responseResult, signatures: {}, logs: [], } } const updating = async () => { while (state.updating) { await rest(20) } } export const LitModule = { config, setContract, getAuthSig, storePublicIdeaKeyOnLitForNftId, storeTemporaryPublicIdeaKeyOnLit, updateToDefinitiveAccessControlConditions, recoverPublicIdeaKeyFromLitForNftId, // runJSFallback, runJS, testJS, }