@ixily/activ
Version:
Alpha Capture Trade Idea Verification. Blockchain ownership proven trade ideas and strategies.
829 lines (791 loc) • 19.8 kB
text/typescript
import {
CONTRACT_INTERFACES,
CONTRACT_TOOLS,
IPaging,
IPortfolioRebalanceAssetOpaque,
IPortfolioRebalanceOpaque,
IPortfolioView,
IStrategyWithCreator,
IWeb3AuthorizationOptions,
Mess,
MyMessDbServer,
getDataWithPaging,
postQueryIdeasFilterAndPagination,
voidPaging,
} from '../..'
import { MyIdeaKeys } from '../../interfaces/chunks/my-idea-keys.i'
import { ConfigModule } from './config.module'
const state = {
servers: undefined as MyMessDbServer[] | undefined,
}
const startLocalServer = async (details: IWeb3AuthorizationOptions) => {
if (state.servers === undefined) {
state.servers = []
state.servers = await Mess.serveContractsDb([
{
blockchainNetwork: 'amoy',
contractName: 'v4',
details,
},
{
blockchainNetwork: 'polygon',
contractName: 'v4',
details,
},
])
state.servers.forEach((server) => {
server.error$.subscribe((error) => {
if (error !== undefined) {
console.error(error)
throw error
}
})
})
} else {
state.servers.forEach((server) => {
server.resume()
})
}
}
ConfigModule.getConfigUpdatedStream().subscribe((config) => {
if (config !== undefined) {
if (config.dataSource !== undefined) {
if (config.dataSource.publicCache.source === 'local') {
if (config.dataSource.publicCache.autoServe !== false) {
startLocalServer(config.web3AuthorizationOptions)
}
}
}
}
})
const pauseLocalServer = () => {
if (state.servers !== undefined) {
state.servers.forEach((server) => {
server.pause()
})
}
}
const listContracts = async (): Promise<string[]> => {
return Mess.contractsInMemoryDbView.listAllContracts()
}
const getCreator = async (
contract: string,
creatorWallet: string,
): Promise<CONTRACT_INTERFACES.ITradeIdeaCreator> => {
return Mess.contractsInMemoryDbView.getCreator(contract, creatorWallet)
}
const getIdeaByUniqueId = async (
uniqueIdeaId: string,
): Promise<CONTRACT_INTERFACES.ITradeIdea> => {
return Mess.contractsInMemoryDbView.getIdeaData(uniqueIdeaId)
}
const listCreatorStrategies = async (
contract: string,
creatorWallet: string,
page: number = 1,
limit: number = 5,
): Promise<IPaging<IStrategyWithCreator>> => {
try {
const preCut =
await Mess.contractsInMemoryDbView.listContractCreatorStrategies(
contract,
creatorWallet,
)
preCut.reverse()
const preInflate = await getDataWithPaging<string>({
data: preCut as string[],
paging: {
page: page || 1,
limit: limit || 5,
},
})
const result: IPaging<IStrategyWithCreator> = {
...preInflate,
data: await Promise.all(
preInflate.data.map((strategyKey) =>
Mess.contractsInMemoryDbView.getStrategyWithCreator(
strategyKey,
),
),
),
}
return result
} catch (err: any) {
if (typeof err.message === 'string') {
if (
err.message.indexOf('No creator found for creatorWallet') !== -1
) {
return voidPaging<IStrategyWithCreator>(page, limit)
} else {
throw err
}
} else {
throw err
}
}
}
const listStrategiesWithAccessibleIdeasBy = async (
contract: string,
accessorWallet: string,
page: number = 1,
limit: number = 5,
): Promise<IPaging<IStrategyWithCreator>> => {
try {
const preCut =
await Mess.contractsInMemoryDbView.listContractUserWithAccessibleIdeasStrategies(
contract,
accessorWallet,
)
const preInflate = await getDataWithPaging<string>({
data: preCut as string[],
paging: {
page: page || 1,
limit: limit || 5,
},
})
const result: IPaging<IStrategyWithCreator> = {
...preInflate,
data: await Promise.all(
(preCut as string[]).map((strategyKey) =>
Mess.contractsInMemoryDbView.getStrategyWithCreator(
strategyKey,
),
),
),
}
return result
} catch (err: any) {
if (typeof err.message === 'string') {
if (
err.message.indexOf(
'No contractDb found for uniqueContractKey:',
) !== -1
) {
return voidPaging<IStrategyWithCreator>(page, limit)
} else {
throw err
}
} else {
throw err
}
}
}
const listStrategiesSubscribedToBy = async (
contract: string,
accessorWallet: string,
page: number = 1,
limit: number = 5,
): Promise<IPaging<IStrategyWithCreator>> => {
try {
const preCut =
await Mess.contractsInMemoryDbView.listContractUserSubscribedToIdeasStrategies(
contract,
accessorWallet,
)
const preInflate = await getDataWithPaging<string>({
data: preCut as string[],
paging: {
page: page || 1,
limit: limit || 5,
},
})
const result: IPaging<IStrategyWithCreator> = {
...preInflate,
data: await Promise.all(
(preCut as string[]).map((strategyKey) =>
Mess.contractsInMemoryDbView.getStrategyWithCreator(
strategyKey,
),
),
),
}
return result
} catch (err: any) {
if (typeof err.message === 'string') {
if (
err.message.indexOf(
'No contractDb found for uniqueContractKey:',
) !== -1
) {
return voidPaging<IStrategyWithCreator>(page, limit)
} else {
throw err
}
} else {
throw err
}
}
}
const listStrategiesPublic = async (
contract?: string,
page: number = 1,
limit: number = 5,
): Promise<IPaging<IStrategyWithCreator>> => {
let contracts: string[] = []
if (contract !== undefined) {
if (typeof contract === 'string') {
if (contract.length > 1) {
const keyContracts =
await Mess.contractsInMemoryDbView.listAllContracts()
if (
keyContracts.find((one) => one === contract) !== undefined
) {
contracts.push(contract)
} else {
// not fount contract key error
return voidPaging<IStrategyWithCreator>(page, limit)
}
} else {
// not fount contract key error
return voidPaging<IStrategyWithCreator>(page, limit)
}
} else {
// not fount contract key error
return voidPaging<IStrategyWithCreator>(page, limit)
}
}
// console.log('&&&&&&&&')
// console.log('contracts')
// console.log(contracts)
// console.log('&&&&&&&&')
if (contracts.length === 0) {
contracts = [...(await Mess.contractsInMemoryDbView.listAllContracts())]
}
const allData = await Promise.all(
contracts.map((contract) =>
(async () => {
// console.log('contract')
// console.log(contract)
const data = (
await Mess.contractsInMemoryDbView.listContractWithPublicIdeasStrategies(
contract,
)
).reverse()
// console.log('data')
// console.log(data)
return data
})(),
),
)
// console.log('allData')
// console.log(allData)
const preCut = CONTRACT_TOOLS.deterministicEvenlyMixedArray(allData)
const preInflate = await getDataWithPaging<string>({
data: preCut as string[],
paging: {
page: page || 1,
limit: limit || 5,
},
})
// contract here is unique contract key. we need to translate it into right strategy chain
const result: IPaging<IStrategyWithCreator> = {
...preInflate,
data: await Promise.all(
preInflate.data.map((strategyKey) =>
Mess.contractsInMemoryDbView.getStrategyWithCreator(
strategyKey,
),
),
),
}
return result
}
const getPublicStrategyWithCreator = async (
strategyUniqueKey: string,
): Promise<IStrategyWithCreator> => {
return Mess.contractsInMemoryDbView.getStrategyWithCreator(
strategyUniqueKey,
)
}
const listIdeasUniqueIndexesByLatest = async (
contract: string,
page: number = 1,
limit: number = 5,
): Promise<IPaging<string>> => {
const preCut =
await Mess.contractsInMemoryDbView.listAllIdeasIndexesByContract(
contract,
)
const posReverse = preCut.reverse()
const preInflate = await getDataWithPaging<string>({
data: posReverse as string[],
paging: {
page: page || 1,
limit: limit || 5,
},
})
return preInflate
}
const listPublicIdeasUniqueIndexesByLatest = async (
contract: string,
page: number = 1,
limit: number = 5,
): Promise<IPaging<string>> => {
const preReverse =
await Mess.contractsInMemoryDbView.listAllPublicIdeasIndexesByContract(
contract,
)
const preCut = preReverse.reverse()
const preInflate = await getDataWithPaging<string>({
data: preCut as string[],
paging: {
page: page || 1,
limit: limit || 5,
},
})
return preInflate
}
/*
const listIdeasIndexes = async (
contract: string,
page: number = 1,
limit: number = 5,
): Promise<IPaging<MyIdeaKeys>> => {
const indexes = await listIdeasUniqueIndexesByLatest(contract, page, limit)
const dataKeys = await Promise.all(
indexes.data.map((ideaKey) =>
Mess.contractsInMemoryDbView.getIdeaKeys(ideaKey),
),
)
const result: IPaging<MyIdeaKeys> = {
...indexes,
data: dataKeys,
}
return result
}
*/
const listLatestIdeas = async (
contract: string,
page: number = 1,
limit: number = 5,
): Promise<IPaging<CONTRACT_INTERFACES.ITradeIdea>> => {
const keys = await listIdeasUniqueIndexesByLatest(contract, page, limit)
const result: IPaging<CONTRACT_INTERFACES.ITradeIdea> = {
...keys,
data: await Promise.all(
keys.data.map((ideaKey) =>
Mess.contractsInMemoryDbView.getIdeaData(ideaKey),
),
),
}
return result
}
const listLatestPublicIdeas = async (
contract?: string,
page: number = 1,
limit: number = 5,
): Promise<IPaging<CONTRACT_INTERFACES.ITradeIdea>> => {
let contracts: string[] = []
if (contract !== undefined) {
if (typeof contract === 'string') {
if (contract.length > 1) {
const keyContracts =
await Mess.contractsInMemoryDbView.listAllContracts()
if (
keyContracts.find((one) => one === contract) !== undefined
) {
contracts.push(contract)
} else {
// not fount contract key error
return voidPaging<CONTRACT_INTERFACES.ITradeIdea>(
page,
limit,
)
}
} else {
// not fount contract key error
return voidPaging<CONTRACT_INTERFACES.ITradeIdea>(page, limit)
}
} else {
// not fount contract key error
return voidPaging<CONTRACT_INTERFACES.ITradeIdea>(page, limit)
}
}
if (contracts.length === 0) {
contracts = [...(await Mess.contractsInMemoryDbView.listAllContracts())]
}
const allData = await Promise.all(
contracts.map((contract) =>
(async () => {
// console.log('contract')
// console.log(contract)
const data = (
await Mess.contractsInMemoryDbView.listAllPublicIdeasIndexesByContract(
contract,
)
).reverse()
// console.log('data')
// console.log(data)
return data
})(),
),
)
const preCut = CONTRACT_TOOLS.deterministicEvenlyMixedArray(allData)
const preInflate = await getDataWithPaging<string>({
data: preCut as string[],
paging: {
page: page || 1,
limit: limit || 5,
},
})
const result: IPaging<CONTRACT_INTERFACES.ITradeIdea> = {
...preInflate,
data: await Promise.all(
preInflate.data.map((ideaKey) =>
Mess.contractsInMemoryDbView.getIdeaData(ideaKey),
),
),
}
return result
}
const listCreatorIdeas = async (
contract: string,
creatorWallet: string,
page: number = 1,
limit: number = 5,
filterType: CONTRACT_INTERFACES.ITradeIdeaIdeaKind[] | 'bypass' = 'bypass',
filterIncludeEncrypted: boolean = false,
bypassPaginationAndGetAll: boolean = false,
): Promise<IPaging<CONTRACT_INTERFACES.ITradeIdea>> => {
const preReverse =
await Mess.contractsInMemoryDbView.listCreatedByIdeasIndexesByContract(
contract,
creatorWallet,
)
const preCut = preReverse.reverse()
const postInflate = await Promise.all(
preCut.map((ideaKey) =>
Mess.contractsInMemoryDbView.getIdeaData(ideaKey),
),
)
const postPageFiltered = postQueryIdeasFilterAndPagination(
postInflate,
page,
limit,
filterType,
filterIncludeEncrypted,
bypassPaginationAndGetAll,
)
/*
const preInflate = await getDataWithPaging<string>({
data: preCut as string[],
paging: {
page: page || 1,
limit: limit || 5,
},
})
const result: IPaging<CONTRACT_INTERFACES.ITradeIdea> = {
...preInflate,
data: await Promise.all(
preInflate.data.map((ideaKey) =>
Mess.contractsInMemoryDbView.getIdeaData(ideaKey),
),
),
}
*/
return postPageFiltered
}
const listOwnedIdeas = async (
contract: string,
creatorWallet: string,
page: number = 1,
limit: number = 5,
filterType: CONTRACT_INTERFACES.ITradeIdeaIdeaKind[] | 'bypass' = 'bypass',
filterIncludeEncrypted: boolean = false,
bypassPaginationAndGetAll: boolean = false,
): Promise<IPaging<CONTRACT_INTERFACES.ITradeIdea>> => {
const preCut =
await Mess.contractsInMemoryDbView.listOwnedByIdeasKeysByContract(
contract,
creatorWallet,
)
const onlyLastStagesOfEachIdeaIndexes =
getOnlyLastStagesOfEachIdeaIndexes(preCut)
onlyLastStagesOfEachIdeaIndexes.reverse()
const postInflate = await Promise.all(
onlyLastStagesOfEachIdeaIndexes.map((ideaKey) =>
Mess.contractsInMemoryDbView.getIdeaData(ideaKey),
),
)
const postPageFiltered = postQueryIdeasFilterAndPagination(
postInflate,
page,
limit,
filterType,
filterIncludeEncrypted,
bypassPaginationAndGetAll,
)
/*
const preInflate = await getDataWithPaging<string>({
data: preCut as string[],
paging: {
page: page || 1,
limit: limit || 5,
},
})
const result: IPaging<CONTRACT_INTERFACES.ITradeIdea> = {
...preInflate,
data: await Promise.all(
preInflate.data.map((ideaKey) =>
Mess.contractsInMemoryDbView.getIdeaData(ideaKey),
),
),
}
*/
return postPageFiltered
}
const getOnlyLastStagesOfEachIdeaIndexes = (ideas: MyIdeaKeys[]): string[] => {
const alreadyKey = new Map<number, string>()
const ideaKeysOrdered: number[] = []
for (const idKey of ideas) {
if (!alreadyKey.has(idKey.ideaKey)) {
ideaKeysOrdered.push(idKey.ideaKey)
}
alreadyKey.set(idKey.ideaKey, idKey.ideaIndex)
}
// console.log('ideaKeysOrdered')
// console.log(ideaKeysOrdered)
const onlyLatestStagesOrderedIndexes = ideaKeysOrdered.map(
(each) => alreadyKey.get(each)!,
)
return onlyLatestStagesOrderedIndexes
}
const listStrategyIdeas = async (
strategyUniqueKey: string,
page: number = 1,
limit: number = 5,
filterType: CONTRACT_INTERFACES.ITradeIdeaIdeaKind[] | 'bypass' = 'bypass',
filterIncludeEncrypted: boolean = true,
bypassPaginationAndGetAll: boolean = false,
) => {
const preCut =
await Mess.contractsInMemoryDbView.listAllIdeasKeysByStrategy(
strategyUniqueKey,
)
// console.log('preCut')
// console.log(preCut)
const onlyLatestStagesOrderedIndexes =
getOnlyLastStagesOfEachIdeaIndexes(preCut)
// console.log('onlyLatestStagesOrderedIndexes')
// console.log(onlyLatestStagesOrderedIndexes)
onlyLatestStagesOrderedIndexes.reverse()
const postInflate = await Promise.all(
onlyLatestStagesOrderedIndexes.map((ideaKey) =>
Mess.contractsInMemoryDbView.getIdeaData(ideaKey),
),
)
// console.log('postInflate')
// console.log(postInflate)
const postPageFiltered = postQueryIdeasFilterAndPagination(
postInflate,
page,
limit,
filterType,
filterIncludeEncrypted,
bypassPaginationAndGetAll,
)
return postPageFiltered
}
const getStrategyPortfolio = async (
strategyUniqueKey: string,
): Promise<IPortfolioView | 'ENCRYPTED'> => {
const portfolio = await Mess.contractsInMemoryDbView.getStrategyPortfolio(
strategyUniqueKey,
)
return portfolio
}
const listStrategyRebalances = async (
strategyUniqueKey: string,
page: number = 1,
limit: number = 5,
): Promise<IPaging<IPortfolioRebalanceOpaque>> => {
const preCut = await Mess.contractsInMemoryDbView.getStrategyRebalances(
strategyUniqueKey,
)
// console.log('preCut')
// console.log(preCut)
preCut.reverse()
const preInflate = await getDataWithPaging<{
index: number
reference: string
ideaIndexes: string[]
}>({
data: preCut,
paging: {
page: page || 1,
limit: limit || 5,
},
})
const result: IPaging<IPortfolioRebalanceOpaque> = {
...preInflate,
data: await Promise.all(
preInflate.data.map(async (rebalance) => {
let assets = await Promise.all(
rebalance.ideaIndexes.map(async (ideaIndex) => {
const lastIdea =
await Mess.contractsInMemoryDbView.getIdeaData(
ideaIndex,
)
const result: IPortfolioRebalanceAssetOpaque = {
lastIdea,
}
return result
}),
)
assets = assets.filter((asset) => {
let kindClose: boolean = false
if (typeof asset.lastIdea.idea !== 'string') {
if (
(
asset.lastIdea
.idea as CONTRACT_INTERFACES.ITradeIdeaIdea
).kind === 'close'
) {
kindClose = true
}
}
return !kindClose
})
const result: IPortfolioRebalanceOpaque = {
strategyKey: strategyUniqueKey,
reference: rebalance.reference,
totalAssets: assets.length,
assets,
}
return result
}),
),
}
return result
}
const getStrategyRebalance = async (
strategyUniqueKey: string,
rebalanceReference: string,
): Promise<IPortfolioRebalanceOpaque> => {
const rebalance = await Mess.contractsInMemoryDbView.getStrategyRebalance(
strategyUniqueKey,
rebalanceReference,
)
let assets = await Promise.all(
rebalance.ideaIndexes.map(async (ideaIndex) => {
const lastIdea = await Mess.contractsInMemoryDbView.getIdeaData(
ideaIndex,
)
const result: IPortfolioRebalanceAssetOpaque = {
lastIdea,
}
return result
}),
)
assets = assets.filter((asset) => {
let kindClose: boolean = false
if (typeof asset.lastIdea.idea !== 'string') {
if (
(asset.lastIdea.idea as CONTRACT_INTERFACES.ITradeIdeaIdea)
.kind === 'close'
) {
kindClose = true
}
}
return !kindClose
})
const result: IPortfolioRebalanceOpaque = {
strategyKey: strategyUniqueKey,
reference: rebalance.reference,
totalAssets: assets.length,
assets,
}
return result
}
const listStrategyRebalancesInPeriod = async (
strategyUniqueKey: string,
start: number,
end: number,
page: number = 1,
limit: number = 5,
): Promise<IPaging<IPortfolioRebalanceOpaque>> => {
const preCut =
await Mess.contractsInMemoryDbView.getStrategyRebalancesInPeriod(
strategyUniqueKey,
start,
end,
)
const preInflate = await getDataWithPaging<{
index: number
reference: string
ideaIndexes: string[]
}>({
data: preCut,
paging: {
page: page || 1,
limit: limit || 5,
},
})
const result: IPaging<IPortfolioRebalanceOpaque> = {
...preInflate,
data: await Promise.all(
preInflate.data.map(async (rebalance) => {
let assets = await Promise.all(
rebalance.ideaIndexes.map(async (ideaIndex) => {
const lastIdea =
await Mess.contractsInMemoryDbView.getIdeaData(
ideaIndex,
)
const result: IPortfolioRebalanceAssetOpaque = {
lastIdea,
}
return result
}),
)
assets = assets.filter((asset) => {
let kindClose: boolean = false
if (typeof asset.lastIdea.idea !== 'string') {
if (
(
asset.lastIdea
.idea as CONTRACT_INTERFACES.ITradeIdeaIdea
).kind === 'close'
) {
kindClose = true
}
}
return !kindClose
})
const result: IPortfolioRebalanceOpaque = {
strategyKey: strategyUniqueKey,
reference: rebalance.reference,
totalAssets: assets.length,
assets,
}
return result
}),
),
}
return result
}
export const ViewsSourceMessModule = {
startLocalServer,
pauseLocalServer,
//
listContracts,
getCreator,
listCreatorStrategies,
listStrategiesWithAccessibleIdeasBy,
listStrategiesSubscribedToBy,
listStrategiesPublic,
listIdeasUniqueIndexesByLatest,
listLatestIdeas,
listLatestPublicIdeas,
listCreatorIdeas,
listOwnedIdeas,
listStrategyIdeas,
getIdeaByUniqueId,
getPublicStrategyWithCreator,
getStrategyPortfolio,
listStrategyRebalances,
getStrategyRebalance,
listStrategyRebalancesInPeriod,
// listIdeaStagesIndexes,
// getIdeaByNftId,
// listIdeaNftsByStrategy,
}