diff --git a/abis/InstaEvents.json b/abis/InstaEvents.json new file mode 100644 index 0000000..56f7e58 --- /dev/null +++ b/abis/InstaEvents.json @@ -0,0 +1,80 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint64", + "name": "connectorType", + "type": "uint64" + }, + { + "indexed": true, + "internalType": "uint64", + "name": "connectorID", + "type": "uint64" + }, + { + "indexed": true, + "internalType": "uint64", + "name": "accountID", + "type": "uint64" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "eventCode", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "eventData", + "type": "bytes" + } + ], + "name": "LogEvent", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_connectorType", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_connectorID", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "_eventCode", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "_eventData", + "type": "bytes" + } + ], + "name": "emitEvent", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "instaList", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/abis/InstaList.json b/abis/InstaList.json new file mode 100644 index 0000000..9846678 --- /dev/null +++ b/abis/InstaList.json @@ -0,0 +1,221 @@ +[ + { + "inputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "name": "accountAddr", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "accountID", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "name": "accountLink", + "outputs": [ + { + "internalType": "address", + "name": "first", + "type": "address" + }, + { + "internalType": "address", + "name": "last", + "type": "address" + }, + { + "internalType": "uint64", + "name": "count", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "accountList", + "outputs": [ + { + "internalType": "address", + "name": "prev", + "type": "address" + }, + { + "internalType": "address", + "name": "next", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "accounts", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_owner", + "type": "address" + } + ], + "name": "addAuth", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_account", + "type": "address" + } + ], + "name": "init", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "instaIndex", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_owner", + "type": "address" + } + ], + "name": "removeAuth", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "userLink", + "outputs": [ + { + "internalType": "uint64", + "name": "first", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "last", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "count", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "name": "userList", + "outputs": [ + { + "internalType": "uint64", + "name": "prev", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "next", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/schema.graphql b/schema.graphql index d83f269..a2de227 100644 --- a/schema.graphql +++ b/schema.graphql @@ -9,6 +9,7 @@ type User @entity { } type SmartAccount @entity { + "The ID used for the SmartAccount entity is the address of said smart account" id: ID! "Latest enabled owner" @@ -17,7 +18,9 @@ type SmartAccount @entity { "Sender of the creation transaction" creator: User - origin: String! + origin: Bytes! + + accountID: BigInt! "Account module from which this account was created. It holds the connectors linked to this account." accountModule: AccountModule @@ -31,7 +34,10 @@ type SmartAccount @entity { casts: [Cast!]! @derivedFrom(field: "account") "Events that ocurred within this account scope" - events: [SmartAccountEvent!]! @derivedFrom(field: "account") + accountEvents: [SmartAccountEvent!]! @derivedFrom(field: "account") + + "Events triggered by this account withing a connectors' scope" + connectorEvents: [ConnectorEvent!]! @derivedFrom(field: "account") } type AccountModule @entity { @@ -39,12 +45,12 @@ type AccountModule @entity { id: ID! "Base address of the module" - address: String! + address: Bytes! "InstaConnectors contract linked to this module. It holds a list of linked connectors as well as chief/admin information for that contract." connectors: InstaConnector! - check: String + check: Bytes instaIndex: InstaIndex! @@ -56,7 +62,9 @@ type InstaIndex @entity { id: ID! "Address of the current master" - master: String + master: Bytes + + instaListAddress: Bytes accountModules: [AccountModule!]! @derivedFrom(field: "instaIndex") } @@ -71,7 +79,7 @@ type InstaConnector @entity { } type Connector @entity { - "Connector ID includes the ID of the InstaConnector it belongs to and the internal ID of the connector" + "ID used for this entity includes the internal ID of the connector and it's type" id: ID! "Whether this connector is a Static Connector or not." @@ -93,7 +101,10 @@ type Connector @entity { connectorType: BigInt! "Address for said connector" - address: String! + address: Bytes! + + "ConnectorEvents that were triggered for this connector" + events: [ConnectorEvent!]! @derivedFrom(field: "connector") } type Chief @entity { @@ -110,9 +121,9 @@ type Cast @entity { "Account that triggered the cast" account: SmartAccount! - origin: String! + origin: Bytes! - sender: String! + sender: Bytes! value: BigInt! } @@ -129,9 +140,9 @@ type CastEvent implements SmartAccountEvent @entity { account: SmartAccount! - origin: String! + origin: Bytes! - sender: String! + sender: Bytes! value: BigInt! } @@ -159,3 +170,15 @@ type SwitchShieldEvent implements SmartAccountEvent @entity { shield: Boolean! } + +type ConnectorEvent @entity { + id: ID! + + connector: Connector! + + account: SmartAccount! + + eventCode: Bytes! + + eventData: Bytes! +} diff --git a/src/index.ts b/src/index.ts index 54b97c2..3f9ac38 100644 --- a/src/index.ts +++ b/src/index.ts @@ -13,7 +13,8 @@ export { handleLogDisableConnector, handleLogEnableStaticConnector, handleLogAddController, - handleLogRemoveController + handleLogRemoveController, + handleLogEvent } from "./mappings/instaConnectors"; export { diff --git a/src/mappings/instaAccount.ts b/src/mappings/instaAccount.ts index e57ddf3..a7da073 100644 --- a/src/mappings/instaAccount.ts +++ b/src/mappings/instaAccount.ts @@ -31,13 +31,13 @@ export function handleLogCast(event: LogCast): void { let cast = getOrCreateCast(eventId); castEvent.account = account.id; - castEvent.origin = event.params.origin.toHexString(); - castEvent.sender = event.params.sender.toHexString() + castEvent.origin = event.params.origin; + castEvent.sender = event.params.sender castEvent.value = event.params.value; cast.account = account.id; - cast.origin = event.params.origin.toHexString(); - cast.sender = event.params.sender.toHexString() + cast.origin = event.params.origin; + cast.sender = event.params.sender cast.value = event.params.value; castEvent.save(); diff --git a/src/mappings/instaConnectors.ts b/src/mappings/instaConnectors.ts index 4bcdfd9..8a355ac 100644 --- a/src/mappings/instaConnectors.ts +++ b/src/mappings/instaConnectors.ts @@ -5,8 +5,16 @@ import { LogAddController, LogRemoveController } from "../../generated/templates/InstaConnectors/InstaConnectors"; +import { LogEvent } from "../../generated/InstaEvents/InstaEvents"; +import { InstaList } from "../../generated/InstaEvents/InstaList"; +import { log, Address } from "@graphprotocol/graph-ts"; import { Connector as ConnectorContract } from "../../generated/templates/InstaConnectors/Connector"; -import { getOrCreateConnector, getOrCreateChief } from "../utils/helpers"; +import { + getOrCreateConnector, + getOrCreateChief, + getOrCreateConnectorEvent, + getOrCreateInstaIndex +} from "../utils/helpers"; // - event: LogDisable(indexed address) // handler: handleLogDisableConnector @@ -15,15 +23,16 @@ export function handleLogDisableConnector(event: LogDisable): void { let contract = ConnectorContract.bind(event.params.connector); let connectorIDResult = contract.connectorID(); let instaConnectorAddress = event.address.toHexString(); - let entityId = instaConnectorAddress + let entityId = connectorIDResult.value1 + .toString() .concat("-") - .concat(connectorIDResult.value1.toString()); + .concat(connectorIDResult.value0.toString()); let connector = getOrCreateConnector(entityId); connector.isEnabled = false; connector.instaConnector = event.address.toHexString(); connector.name = contract.name(); - connector.address = event.params.connector.toHexString(); + connector.address = event.params.connector connector.connectorType = connectorIDResult.value0; connector.connectorID = connectorIDResult.value1; @@ -37,16 +46,17 @@ export function handleLogEnableConnector(event: LogEnable): void { let contract = ConnectorContract.bind(event.params.connector); let connectorIDResult = contract.connectorID(); let instaConnectorAddress = event.address.toHexString(); - let entityId = instaConnectorAddress + let entityId = connectorIDResult.value1 + .toString() .concat("-") - .concat(connectorIDResult.value1.toString()); + .concat(connectorIDResult.value0.toString()); let connector = getOrCreateConnector(entityId); connector.isEnabled = true; connector.isStatic = false; connector.instaConnector = event.address.toHexString(); connector.name = contract.name(); - connector.address = event.params.connector.toHexString(); + connector.address = event.params.connector; connector.connectorType = connectorIDResult.value0; connector.connectorID = connectorIDResult.value1; @@ -60,16 +70,17 @@ export function handleLogEnableStaticConnector(event: LogEnableStatic): void { let contract = ConnectorContract.bind(event.params.connector); let connectorIDResult = contract.connectorID(); let instaConnectorAddress = event.address.toHexString(); - let entityId = instaConnectorAddress + let entityId = connectorIDResult.value1 + .toString() .concat("-") - .concat(connectorIDResult.value1.toString()); + .concat(connectorIDResult.value0.toString()); let connector = getOrCreateConnector(entityId); connector.isEnabled = true; connector.isStatic = true; connector.instaConnector = instaConnectorAddress; connector.name = contract.name(); - connector.address = event.params.connector.toHexString(); + connector.address = event.params.connector; connector.connectorType = connectorIDResult.value0; connector.connectorID = connectorIDResult.value1; @@ -80,22 +91,52 @@ export function handleLogEnableStaticConnector(event: LogEnableStatic): void { // handler: handleLogAddController export function handleLogAddController(event: LogAddController): void { - let chief = getOrCreateChief(event.params.addr.toHexString()) + let chief = getOrCreateChief(event.params.addr.toHexString()); chief.isActive = true; chief.instaConnector = event.address.toHexString(); - chief.save() + chief.save(); } // - event: LogRemoveController(indexed address) // handler: handleLogRemoveController export function handleLogRemoveController(event: LogRemoveController): void { - let chief = getOrCreateChief(event.params.addr.toHexString()) + let chief = getOrCreateChief(event.params.addr.toHexString()); chief.isActive = false; chief.instaConnector = event.address.toHexString(); - chief.save() + chief.save(); +} + +// - event: LogEvent(uint64,indexed uint64,indexed uint64,indexed bytes32,bytes) +// handler: handleLogEvent + +export function handleLogEvent(event: LogEvent): void { + let entityId = event.params.connectorID + .toString() + .concat("-") + .concat(event.params.connectorType.toString()); + let connector = getOrCreateConnector(entityId, false); + + if (connector == null) { + log.error("Connector '{}' doesn't exist.", [entityId]); + } else { + let index = getOrCreateInstaIndex(); + let instaListContract = InstaList.bind(index.instaListAddress as Address); + let accountAddress = instaListContract.accountAddr(event.params.accountID); + let eventId = event.transaction.hash + .toHexString() + .concat("-") + .concat(event.logIndex.toString()); + let connectorEvent = getOrCreateConnectorEvent(eventId); + connectorEvent.account = accountAddress.toHexString(); + connectorEvent.connector = connector.id; + connectorEvent.eventCode = event.params.eventCode; + connectorEvent.eventData = event.params.eventData; + + connectorEvent.save(); + } } diff --git a/src/mappings/instaIndex.ts b/src/mappings/instaIndex.ts index 9210ad9..c1f1653 100644 --- a/src/mappings/instaIndex.ts +++ b/src/mappings/instaIndex.ts @@ -8,6 +8,8 @@ import { BuildCall, InstaIndex } from "../../generated/InstaIndex/InstaIndex"; +import { InstaList } from "../../generated/InstaIndex/InstaList"; +import { Address } from "@graphprotocol/graph-ts"; import { getOrCreateAccountModule, getOrCreateUser, @@ -27,11 +29,14 @@ export function handleLogAccountCreated(event: LogAccountCreated): void { ); let owner = getOrCreateUser(event.params.owner.toHexString()); let sender = getOrCreateUser(event.params.sender.toHexString()); + let index = getOrCreateInstaIndex(); + let instaListContract = InstaList.bind(index.instaListAddress as Address); smartAccount.owner = owner.id; smartAccount.creator = sender.id; - smartAccount.origin = event.params.origin.toHexString(); + smartAccount.origin = event.params.origin; smartAccount.isEnabled = true; + smartAccount.accountID = instaListContract.accountID(event.params.account); smartAccount.save(); } @@ -47,9 +52,9 @@ export function handleLogNewAccount(event: LogNewAccount): void { let accountModule = getOrCreateAccountModule(accountVersion.toString()); let instaConnector = getOrCreateInstaConnector(event.params._connectors); - accountModule.address = event.params._newAccount.toHexString(); + accountModule.address = event.params._newAccount; accountModule.connectors = instaConnector.id; - accountModule.check = event.params._check.toHexString(); + accountModule.check = event.params._check; accountModule.save(); } @@ -62,7 +67,7 @@ export function handleLogNewCheck(event: LogNewCheck): void { event.params.accountVersion.toString() ); - accountModule.check = event.params.check.toHexString(); + accountModule.check = event.params.check; accountModule.save(); } @@ -73,7 +78,7 @@ export function handleLogNewCheck(event: LogNewCheck): void { export function handleLogNewMaster(event: LogNewMaster): void { let index = getOrCreateInstaIndex(); - index.master = event.params.master.toHexString(); + index.master = event.params.master; index.save(); } @@ -84,19 +89,23 @@ export function handleLogNewMaster(event: LogNewMaster): void { export function handleLogUpdateMaster(event: LogUpdateMaster): void { let index = getOrCreateInstaIndex(); - index.master = event.params.master.toHexString(); + index.master = event.params.master; index.save(); } export function handleSetBasics(call: SetBasicsCall): void { + let instaIndex = getOrCreateInstaIndex(); let accountVersion = InstaIndex.bind(call.to).versionCount(); let accountModule = getOrCreateAccountModule(accountVersion.toString()); let instaConnector = getOrCreateInstaConnector(call.inputs._connectors); - accountModule.address = call.inputs._account.toHexString(); + accountModule.address = call.inputs._account; accountModule.connectors = instaConnector.id; + instaIndex.instaListAddress = call.inputs._list; + + instaIndex.save(); accountModule.save(); } @@ -107,7 +116,7 @@ export function handleBuild(call: BuildCall): void { let owner = getOrCreateUser(call.inputs._owner.toHexString()); smartAccount.owner = owner.id; - smartAccount.origin = call.inputs._origin.toHexString(); + smartAccount.origin = call.inputs._origin; smartAccount.accountModule = call.inputs.accountVersion.toString(); smartAccount.save(); diff --git a/src/utils/helpers/index.ts b/src/utils/helpers/index.ts index 3afafe5..cea5b35 100644 --- a/src/utils/helpers/index.ts +++ b/src/utils/helpers/index.ts @@ -8,7 +8,8 @@ export { export { getOrCreateConnector, getOrCreateInstaConnector, - getOrCreateChief + getOrCreateChief, + getOrCreateConnectorEvent } from "./instaConnectors"; export { diff --git a/src/utils/helpers/instaConnectors.ts b/src/utils/helpers/instaConnectors.ts index 75fc42c..f4c5ef8 100644 --- a/src/utils/helpers/instaConnectors.ts +++ b/src/utils/helpers/instaConnectors.ts @@ -1,5 +1,5 @@ import { InstaConnectors as ConnectorsTemplate } from "../../../generated/templates"; -import { InstaConnector, Connector, Chief } from "../../../generated/schema"; +import { InstaConnector, Connector, Chief, ConnectorEvent } from "../../../generated/schema"; import { Address } from "@graphprotocol/graph-ts"; export function getOrCreateInstaConnector( @@ -43,3 +43,16 @@ export function getOrCreateChief( return chief as Chief; } + +export function getOrCreateConnectorEvent( + id: String, + createIfNotFound: boolean = true +): ConnectorEvent { + let event = ConnectorEvent.load(id); + + if (event == null && createIfNotFound) { + event = new ConnectorEvent(id); + } + + return event as ConnectorEvent; +} diff --git a/src/utils/helpers/instaIndex.ts b/src/utils/helpers/instaIndex.ts index 2b088fc..a0fd868 100644 --- a/src/utils/helpers/instaIndex.ts +++ b/src/utils/helpers/instaIndex.ts @@ -58,10 +58,10 @@ export function getOrCreateAccountModule( } export function getOrCreateInstaIndex(): InstaIndex { - let index = InstaIndex.load("INDEX"); + let index = InstaIndex.load("0x2971adfa57b20e5a416ae5a708a8655a9c74f723"); if (index == null) { - index = new InstaIndex("INDEX"); + index = new InstaIndex("0x2971adfa57b20e5a416ae5a708a8655a9c74f723"); index.save(); } diff --git a/subgraph.yaml b/subgraph.yaml index 94ecec2..340f6e6 100644 --- a/subgraph.yaml +++ b/subgraph.yaml @@ -22,6 +22,8 @@ dataSources: abis: - name: InstaIndex file: ./abis/InstaIndex.json + - name: InstaList + file: ./abis/InstaList.json eventHandlers: - event: LogAccountCreated(address,indexed address,indexed address,indexed address) handler: handleLogAccountCreated @@ -38,6 +40,30 @@ dataSources: handler: handleSetBasics - function: build(address,uint256,address) handler: handleBuild + - kind: ethereum/contract + name: InstaEvents + network: mainnet + source: + address: "0x2af7ea6cb911035f3eb1ed895cb6692c39ecba97" + abi: InstaEvents + startBlock: 9747294 + mapping: + kind: ethereum/events + apiVersion: 0.0.4 + language: wasm/assemblyscript + file: ./src/index.ts + entities: + - SmartAccount + - Connector + - ConnectorEvent + abis: + - name: InstaEvents + file: ./abis/InstaEvents.json + - name: InstaList + file: ./abis/InstaList.json + eventHandlers: + - event: LogEvent(uint64,indexed uint64,indexed uint64,indexed bytes32,bytes) + handler: handleLogEvent templates: - name: InstaConnectors kind: ethereum/contract