@ixily/activ
Version:
Alpha Capture Trade Idea Verification. Blockchain ownership proven trade ideas and strategies.
479 lines (401 loc) • 11.7 kB
text/typescript
const BufferB = require('buffer/').Buffer
import { ethers } from 'ethers'
import { ILitProvider, LIT_ACTIONS, LogModule as log } from '../activ-v4'
import { isNullOrUndefined } from '../activ-v4/tools/chunks/helpers.tool'
// import * as fs from 'fs' // debug code
// import path from 'path' // debug code
/*
NOTE: to use activ from backend the client need install 2 external packages:
* npm install lit-js-sdk@1.2.57 --force
* npm install siwe@1.1.6 --force
*/
import { AccessControlConditions, AuthSig } from '@lit-protocol/types'
let LitJsSdk: any
let Siwe: any
let backendWalletPrivateKey: string | undefined
const checks = {
LitJsSdkCheck: () => {
if (isNullOrUndefined(LitJsSdk)) {
throw new Error('LitJsSdk is not initialized')
}
},
SiweCheck: () => {
if (isNullOrUndefined(Siwe)) {
throw new Error('Siwe is not initialized')
}
},
}
const globalCheck = () => {
// NOTE: automate this in a future
checks.LitJsSdkCheck()
checks.SiweCheck()
}
const init = async (externalPackages: {
LitJsSdkInstance: any
SiweInstance?: any
backendWalletPrivateKey?: string
}) => {
LitJsSdk = externalPackages?.LitJsSdkInstance
Siwe = externalPackages?.SiweInstance
backendWalletPrivateKey =
externalPackages?.backendWalletPrivateKey || undefined
}
const getEncryptionClient = async () => {
globalCheck()
const client = new (LitJsSdk as any).LitNodeClientNodeJs({
alertWhenUnauthorized: true,
debug: false,
})
await client.connect()
return client
}
const getActionsClient = async (nodes: number = 10) => {
globalCheck()
// Dev mark nodes
if (LIT_ACTIONS.USE_LIT_ACTION_TEST_CODE) {
nodes = LIT_ACTIONS.USE_LIT_ACTION_TEST_CODE_NODES
}
const client = new LitJsSdk.LitNodeClientNodeJs({
alertWhenUnauthorized: true,
minNodeCount: nodes,
litNetwork: 'serrano',
// debug: true,
debug: LIT_ACTIONS.USE_LIT_ACTION_TEST_CODE,
})
// console.log('connectin lit network')
await client.connect()
return client
}
// const base64StringToBlob = async (base64: string): Promise<Blob> => {
// const response = await fetch(base64)
// console.log(response)
// return (await response.blob()) as Blob
// }
const base64StringToBlob = (base64Data: string): Blob => {
// console.log('base64Data:')
// console.log(base64Data)
const contentType = 'application/octet-stream;base64'
const begin = 'data:' + contentType + ','
const base64DataNoBegin = base64Data.replace(begin, '')
// console.log('base64DataNoBegin:')
// console.log(base64DataNoBegin)
const sliceSize = 1024
const byteCharacters = BufferB.from(base64DataNoBegin, 'base64').toString(
'latin1',
)
const bytesLength = byteCharacters.length
const slicesCount = Math.ceil(bytesLength / sliceSize)
const byteArrays = new Array(slicesCount)
for (let sliceIndex = 0; sliceIndex < slicesCount; ++sliceIndex) {
const begin = sliceIndex * sliceSize
const end = Math.min(begin + sliceSize, bytesLength)
const bytes = new Array(end - begin)
for (let offset = begin, i = 0; offset < end; ++i, ++offset) {
bytes[i] = byteCharacters[offset].charCodeAt(0)
}
byteArrays[sliceIndex] = new Uint8Array(bytes)
}
const blob = new Blob(byteArrays, { type: contentType })
// console.log('blob:')
// console.log(await blobToBase64String(blob))
return blob
}
const blobToBase64String = async (blob: Blob): Promise<string> => {
const buffer = await blob.arrayBuffer()
const base64 = BufferB.from(buffer).toString('base64')
return 'data:application/octet-stream;base64,' + base64
}
const getAuthSig = async (): Promise<AuthSig> => {
globalCheck()
// console.log('backendWalletPrivateKey')
// console.log(backendWalletPrivateKey)
const signer = new ethers.Wallet(backendWalletPrivateKey as string)
// console.log('signer')
// console.log(signer)
let address: string | undefined
if (signer.address !== undefined) {
if (typeof signer.address == 'string') {
if (signer.address.length > 0) {
address = signer.address
}
}
}
if (address === undefined) {
address = await signer.getAddress()
}
// console.log('address')
// console.log(address)
const siweMessage = new Siwe.SiweMessage({
domain: 'ixily.io',
address: address!,
statement:
'I do agree share my wallet authority with Lit Protocol nodes for the purposes of proofing ownership and encryption of my trade ideas.',
uri: 'https://ixily.io',
version: '1',
chainId: 1,
})
const messageToSign = siweMessage.prepareMessage()
const sig = await signer?.signMessage(messageToSign)
const authSig: AuthSig = {
// messageToSign,
sig,
derivedVia: 'web3.eth.personal.sign',
signedMessage: messageToSign,
address,
}
return authSig
}
const encryptString = async (
message: string,
): Promise<{
encryptedString: string
symmetricKey: string
authSig: AuthSig
}> => {
globalCheck()
const authSig = await getAuthSig()
const { symmetricKey, encryptedString } = await LitJsSdk.encryptString(
message,
)
// console.log(
// '[lit-node-provider] encryptString (encryptedString)',
// encryptedString,
// )
const symmetricKeyStr = LitJsSdk.uint8arrayToString(symmetricKey, 'base16')
// console.log(
// '[lit-node-provider] encryptString (symmetricKey)',
// symmetricKeyStr,
// )
// console.log('typeof symmetricKeyStr:')
// console.log(typeof symmetricKeyStr)
// console.log('symmetricKeyStr:')
// console.log(symmetricKeyStr)
const base64: string = await blobToBase64String(encryptedString)
// console.log('base64')
// console.log(base64)
// console.log('[lit-node-provider] encryptString (base64)', base64)
return {
encryptedString: base64,
symmetricKey: symmetricKeyStr,
authSig,
}
}
const saveKey = async (
client: any,
symmetricKey: string,
accessControlConditions: AccessControlConditions,
authSig: AuthSig,
chain: string,
permanent: boolean = true,
): Promise<{
encryptedSymmetricKey: any
encryptedSymmetricKeyString: string
}> => {
globalCheck()
const encryptedSymmetricKey = await client!.saveEncryptionKey({
accessControlConditions,
symmetricKey: LitJsSdk.uint8arrayFromString(symmetricKey, 'base16'),
authSig,
chain,
permanent: permanent === true ? 1 : undefined,
})
// console.log('encryptedSymmetricKey')
// console.log(encryptedSymmetricKey)
const encryptedSymmetricKeyString = LitJsSdk.uint8arrayToString(
encryptedSymmetricKey,
'base16',
)
// console.log('encryptedSymmetricKeyString')
// console.log(encryptedSymmetricKeyString)
return {
encryptedSymmetricKey,
encryptedSymmetricKeyString,
}
}
const updateConditionsKey = async (
client: any,
encryptedSymmetricKey: any,
symmetricKey: string,
accessControlConditions: AccessControlConditions,
authSig: AuthSig,
chain: string,
permanent: boolean = true,
): Promise<void> => {
globalCheck()
await client!.saveEncryptionKey({
encryptedSymmetricKey,
accessControlConditions,
symmetricKey: LitJsSdk.uint8arrayFromString(symmetricKey, 'base16'),
authSig,
chain,
permanent: permanent === true ? 1 : undefined,
})
}
const recoverString = async (
client: any,
encryptedString: string,
encryptedSymmetricKey: string,
accessControlConditions: AccessControlConditions,
chain: string,
): Promise<string> => {
globalCheck()
// console.log(
// 'lit-node-provider.module [recoverString] (encryptedString)',
// encryptedString,
// )
// console.log(
// 'lit-node-provider.module [recoverString] (encryptedSymmetricKey)',
// encryptedSymmetricKey,
// )
// console.log(
// 'lit-node-provider.module [recoverString] (accessControlConditions)',
// accessControlConditions,
// )
// console.log(
// 'lit-node-provider.module [recoverString] (accessControlConditionsStr)',
// JSON.stringify(accessControlConditions),
// )
const authSig = await getAuthSig().catch((err: any) => {
console.error(
'lit-node-provider.module [recoverString] (authSig) ERROR',
err.message,
)
throw err
})
// console.log('lit-node-provider.module [recoverString] (authSig)', authSig)
const encryptionKey = await client!.getEncryptionKey({
accessControlConditions,
toDecrypt: encryptedSymmetricKey,
chain,
authSig,
})
// console.log(
// 'lit-node-provider.module [recoverString] (encryptionKey)',
// encryptionKey,
// )
const blob = await base64StringToBlob(encryptedString)
// console.log('lit-node-provider.module [recoverString] (blob)', blob)
const decryptedString = await LitJsSdk.decryptString(blob, encryptionKey)
// console.log(
// 'lit-node-provider.module [recoverString] (decryptedString)',
// decryptedString,
// )
return decryptedString
}
const runJSFallback = async <T>(
javascriptCode: string,
params: any,
): Promise<{
response: T
}> => {
globalCheck()
// console.log('[lit-node-provider] pre runJSFallback')
const authSig = await getAuthSig()
// console.log('[lit-node-provider] runJSFallback (authSig)', authSig)
const litNodeClient = new LitJsSdk.LitNodeClientNodeJs({
alertWhenUnauthorized: false,
// minNodeCount: 3,
litNetwork: 'jalapeno',
debug: false,
})
await litNodeClient.connect()
const litActionCode = javascriptCode
const litActionResponse = await litNodeClient.executeJs({
code: litActionCode,
jsParams: params,
authSig,
})
// console.log('runJS (litActionResponse)', litActionResponse)
const response = litActionResponse.response as unknown as T
const finalResponse = {
response,
}
// console.log('runJS (finalResponse)', finalResponse)
return finalResponse
}
const runJS = async (
client: any,
ipfsId: string,
publicKey: string,
chain: string,
params?: any,
nodes: number = 10,
): Promise<any> => {
globalCheck()
const authSig = await getAuthSig()
// Dev mark nodes
if (LIT_ACTIONS.USE_LIT_ACTION_TEST_CODE) {
nodes = LIT_ACTIONS.USE_LIT_ACTION_TEST_CODE_NODES
}
// delete params.executionNonce
// delete params.commonCache
// console.log('calling function')
// console.log('params:')
// console.log(params)
// console.log('ipfsId:')
// console.log(ipfsId)
// console.log('publicKey:')
// console.log(publicKey)
// console.log('nodes:')
// console.log(nodes)
// const litActionResponse = await (
// litNodeClient as auxiliarLit.LitNodeClientNodeJs
// )
// console.log('params')
// console.log(params)
// console.log('ipfsId')
// console.log(ipfsId)
// console.log('called lit action ipfsId: ' + ipfsId)
// console.log('lit js called with params: ')
// console.log(params)
if (LIT_ACTIONS.USE_LIT_ACTION_TEST_CODE) {
console.log('LIT_ACTIONS.USE_LIT_ACTION_TEST_CODE => true')
}
const jsParams = {
ipfsId,
publicKey,
...params,
debug: false,
// debug: LIT_ACTIONS.USE_LIT_ACTION_TEST_CODE,
debugSkipSignature: false,
}
// console.log('jsParams:')
// console.log(jsParams)
const litActionResponse = await client.executeJs({
code: LIT_ACTIONS.USE_LIT_ACTION_TEST_CODE
? LIT_ACTIONS.GET_PRICE_TESTCODE_V2_CODE
: undefined,
ipfsId: LIT_ACTIONS.USE_LIT_ACTION_TEST_CODE ? undefined : ipfsId,
jsParams,
authSig,
debug: true,
targetNodeRange: nodes,
})
if (LIT_ACTIONS.USE_LIT_ACTION_TEST_CODE) {
console.log('runJS (litActionResponse)')
console.log(litActionResponse)
}
const { response, logs } = litActionResponse
// console.log('litActionResponse')
// console.log(litActionResponse)
log.dev('lit action logs:')
log.dev(logs)
if (LIT_ACTIONS.USE_LIT_ACTION_TEST_CODE) {
console.log('runJS (finalResponse)', response)
throw new Error('USE_LIT_ACTION_TEST_CODE check breakpoint')
}
return litActionResponse
}
export const LitNodeProviderModule: ILitProvider = {
isBrowser: false,
init,
getEncryptionClient,
getActionsClient,
getAuthSig,
saveKey,
recoverString,
encryptString,
updateConditionsKey,
runJSFallback,
runJS,
}