diff --git a/src/mappings/contractHandlers.ts b/src/mappings/contractHandlers.ts index e6cadd1..6a22972 100644 --- a/src/mappings/contractHandlers.ts +++ b/src/mappings/contractHandlers.ts @@ -1,22 +1,17 @@ import type { CosmosMessage } from "@subql/types-cosmos"; import type { MsgStoreCode } from "cosmjs-types/cosmwasm/wasm/v1/tx"; -import { Contract } from "../types"; -import { findEventAttribute } from "./helper"; - -enum AccessType { - ACCESS_TYPE_UNSPECIFIED = 0, - ACCESS_TYPE_NOBODY = 1, - ACCESS_TYPE_ONLY_ADDRESS = 2, - ACCESS_TYPE_EVERYBODY = 3, - ACCESS_TYPE_ANY_OF_ADDRESSES = 4, - UNRECOGNIZED = -1, -} +import { AccessType } from "cosmjs-types/cosmwasm/wasm/v1/types"; +import { Account, Contract, ContractPermissionAccount } from "../types"; +import { contractPermissionAccountId, findEventAttribute } from "./helper"; export const handleStoreContract = async ( msg: CosmosMessage, ): Promise => { - const id = findEventAttribute(msg.tx.tx.events, "store_code", "code_id") - ?.value; + const contractId = findEventAttribute( + msg.tx.tx.events, + "store_code", + "code_id", + )?.value; const dataHash = findEventAttribute( msg.tx.tx.events, @@ -24,22 +19,60 @@ export const handleStoreContract = async ( "code_checksum", )?.value; - if (!id || !dataHash) { + if (!contractId || !dataHash) { return; } - const { instantiatePermission: instantiatePermissionWithEnums, sender } = - msg.msg.decodedMsg; + const { instantiatePermission, sender } = msg.msg.decodedMsg; + const senderAccount = await Account.get(sender); - const instantiatePermission = instantiatePermissionWithEnums && { - ...instantiatePermissionWithEnums, - permission: AccessType[instantiatePermissionWithEnums.permission], - }; + if (!senderAccount) { + const publicKey = msg.tx.decodedTx.authInfo.signerInfos.find( + (signerInfo) => signerInfo.publicKey, + )?.publicKey; + + await Account.create({ + id: sender, + pubKey: publicKey && { + typeUrl: publicKey.typeUrl, + key: Buffer.from(publicKey.value).toString("base64"), + }, + balances: [ + { + denom: "uknow", + amount: "0", + }, + ], + }).save(); + } + + const permission = + instantiatePermission && AccessType[instantiatePermission.permission]; await Contract.create({ - id, + id: contractId, dataHash, - creator: sender, - instantiatePermission, + creatorId: sender, + permission, }).save(); + + for (const permissionAddress in instantiatePermission?.addresses) { + if (!(await Account.get(permissionAddress))) { + await Account.create({ + id: permissionAddress, + balances: [ + { + denom: "uknow", + amount: "0", + }, + ], + }).save(); + } + + await ContractPermissionAccount.create({ + id: contractPermissionAccountId(contractId, sender), + contractId: permissionAddress, + accountId: sender, + }).save(); + } }; diff --git a/src/mappings/helper.ts b/src/mappings/helper.ts index 3784569..5d4ef0c 100644 --- a/src/mappings/helper.ts +++ b/src/mappings/helper.ts @@ -8,6 +8,16 @@ import type { export const messageId = (msg: CosmosMessage | CosmosEvent): string => `${msg.tx.hash}-${msg.idx}`; +export const objectariumObjectPinId = ( + objectId: string, + sender: string, +): string => `${objectId}-${sender}`; + +export const contractPermissionAccountId = ( + contractId: string, + account: string, +): string => `${contractId}-${account}`; + export const findEvent = ( events: Readonly, event: string, diff --git a/src/mappings/objectariumHandlers.ts b/src/mappings/objectariumHandlers.ts index adc4924..4c23985 100644 --- a/src/mappings/objectariumHandlers.ts +++ b/src/mappings/objectariumHandlers.ts @@ -8,8 +8,14 @@ import { Objectarium, BucketConfig, BucketLimits, + ObjectariumObjectPin, + Account, } from "../types"; -import { findEventAttribute, referenceEntityInMessage } from "./helper"; +import { + findEventAttribute, + objectariumObjectPinId, + referenceEntityInMessage, +} from "./helper"; import type { Event } from "@cosmjs/tendermint-rpc/build/tendermint37"; type StoreObject = { @@ -54,15 +60,43 @@ export const handleStoreObject = async ( } const { sender, contract } = msg.msg.decodedMsg; - const { pin: isPinned } = msg.msg.decodedMsg.msg.store_object; + const senderAccount = await Account.get(sender); + + if (!senderAccount) { + const publicKey = msg.tx.decodedTx.authInfo.signerInfos.find( + (signerInfo) => signerInfo.publicKey, + )?.publicKey; + + await Account.create({ + id: msg.msg.decodedMsg.sender, + pubKey: publicKey && { + typeUrl: publicKey.typeUrl, + key: Buffer.from(publicKey.value).toString("base64"), + }, + balances: [ + { + denom: "uknow", + amount: "0", + }, + ], + }).save(); + } await ObjectariumObject.create({ id: objectId, - sender, + senderId: sender, objectariumId: contract, - pins: isPinned ? [sender] : [], }).save(); + const { pin: isPinned } = msg.msg.decodedMsg.msg.store_object; + + isPinned && + (await ObjectariumObjectPin.create({ + id: objectariumObjectPinId(objectId, sender), + objectariumObjectId: objectId, + accountId: sender, + }).save()); + await referenceEntityInMessage(msg, { messageField: "objectariumObjectId", id: objectId, @@ -87,43 +121,43 @@ export const handleForgetObject = async ( export const handlePinObject = async ( msg: CosmosMessage, ): Promise => { - const object = await retrieveObjectariumObject(msg); - if (!object) { + const objectId = objectariumObjectId(msg.tx.tx.events); + if (!objectId) { return; } const { sender } = msg.msg.decodedMsg; - - if (!object.pins.includes(sender)) { - object.pins.push(sender); - await object.save(); + const objectPin = ObjectariumObjectPin.get( + objectariumObjectPinId(objectId, sender), + ); + + if (!objectPin) { + await ObjectariumObjectPin.create({ + id: objectariumObjectPinId(objectId, sender), + objectariumObjectId: objectId, + accountId: sender, + }).save(); } await referenceEntityInMessage(msg, { messageField: "objectariumObjectId", - id: object.id, + id: objectId, }); }; export const handleUnpinObject = async ( msg: CosmosMessage, ): Promise => { - const object = await retrieveObjectariumObject(msg); - if (!object) { + const objectId = objectariumObjectId(msg.tx.tx.events); + if (!objectId) { return; } - const { sender } = msg.msg.decodedMsg; - const filteredPins = object.pins.filter((address) => address !== sender); - - if (filteredPins.length !== object.pins.length) { - object.pins = filteredPins; - await object.save(); - } + await ObjectariumObjectPin.remove(objectariumObjectPinId(objectId, sender)); await referenceEntityInMessage(msg, { messageField: "objectariumObjectId", - id: object.id, + id: objectId, }); }; @@ -153,6 +187,7 @@ export const handleInitObjectarium = async ( const { sender, + admin, label, msg: { bucket, limits: bucketLimits, config: bucketConfig }, } = msg.msg.decodedMsg; @@ -170,7 +205,8 @@ export const handleInitObjectarium = async ( await Objectarium.create({ id: contractAddress, - owner: sender, + creatorId: sender, + ownerId: admin, label, name: bucket, config,