From 5b933e57a8f63f2bd870d3b1d026ef84f4907cca Mon Sep 17 00:00:00 2001 From: Volod Date: Thu, 10 Jul 2025 10:25:48 -0400 Subject: [PATCH 01/22] feat: ABIs --- abis/v5/DataPermissionImplementation.json | 1159 ++++++++++++++++++++ abis/v5/DataRegistryImplementation.json | 1188 +++++++++++++++++++++ 2 files changed, 2347 insertions(+) create mode 100644 abis/v5/DataPermissionImplementation.json create mode 100644 abis/v5/DataRegistryImplementation.json diff --git a/abis/v5/DataPermissionImplementation.json b/abis/v5/DataPermissionImplementation.json new file mode 100644 index 0000000..03bd73a --- /dev/null +++ b/abis/v5/DataPermissionImplementation.json @@ -0,0 +1,1159 @@ +[ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "AccessControlBadConfirmation", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "neededRole", + "type": "bytes32" + } + ], + "name": "AccessControlUnauthorizedAccount", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + } + ], + "name": "AddressEmptyCode", + "type": "error" + }, + { + "inputs": [], + "name": "ECDSAInvalidSignature", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "length", + "type": "uint256" + } + ], + "name": "ECDSAInvalidSignatureLength", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "ECDSAInvalidSignatureS", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "ERC1967InvalidImplementation", + "type": "error" + }, + { + "inputs": [], + "name": "ERC1967NonPayable", + "type": "error" + }, + { + "inputs": [], + "name": "EmptyGrant", + "type": "error" + }, + { + "inputs": [], + "name": "EmptyUrl", + "type": "error" + }, + { + "inputs": [], + "name": "EnforcedPause", + "type": "error" + }, + { + "inputs": [], + "name": "ExpectedPause", + "type": "error" + }, + { + "inputs": [], + "name": "FailedInnerCall", + "type": "error" + }, + { + "inputs": [], + "name": "GrantAlreadyUsed", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidInitialization", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "expectedNonce", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "providedNonce", + "type": "uint256" + } + ], + "name": "InvalidNonce", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidSignature", + "type": "error" + }, + { + "inputs": [], + "name": "NotInitializing", + "type": "error" + }, + { + "inputs": [], + "name": "ServerAlreadyRegistered", + "type": "error" + }, + { + "inputs": [], + "name": "ServerNotFound", + "type": "error" + }, + { + "inputs": [], + "name": "ServerNotTrusted", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "existingUrl", + "type": "string" + }, + { + "internalType": "string", + "name": "providedUrl", + "type": "string" + } + ], + "name": "ServerUrlMismatch", + "type": "error" + }, + { + "inputs": [], + "name": "UUPSUnauthorizedCallContext", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "slot", + "type": "bytes32" + } + ], + "name": "UUPSUnsupportedProxiableUUID", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddress", + "type": "error" + }, + { + "anonymous": false, + "inputs": [], + "name": "EIP712DomainChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint64", + "name": "version", + "type": "uint64" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "permissionId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": false, + "internalType": "string", + "name": "grant", + "type": "string" + } + ], + "name": "PermissionAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "previousAdminRole", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "newAdminRole", + "type": "bytes32" + } + ], + "name": "RoleAdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "serverId", + "type": "address" + }, + { + "indexed": false, + "internalType": "string", + "name": "url", + "type": "string" + } + ], + "name": "ServerAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "serverId", + "type": "address" + }, + { + "indexed": false, + "internalType": "string", + "name": "serverUrl", + "type": "string" + } + ], + "name": "ServerTrusted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "serverId", + "type": "address" + } + ], + "name": "ServerUntrusted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "inputs": [], + "name": "DEFAULT_ADMIN_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAINTAINER_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "UPGRADE_INTERFACE_VERSION", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "string", + "name": "grant", + "type": "string" + } + ], + "internalType": "struct IDataPermission.PermissionInput", + "name": "permission", + "type": "tuple" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "name": "addPermission", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "eip712Domain", + "outputs": [ + { + "internalType": "bytes1", + "name": "fields", + "type": "bytes1" + }, + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "version", + "type": "string" + }, + { + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "verifyingContract", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "salt", + "type": "bytes32" + }, + { + "internalType": "uint256[]", + "name": "extensions", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleAdmin", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRole", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "trustedForwarderAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "ownerAddress", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "forwarder", + "type": "address" + } + ], + "name": "isTrustedForwarder", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes[]", + "name": "data", + "type": "bytes[]" + } + ], + "name": "multicall", + "outputs": [ + { + "internalType": "bytes[]", + "name": "results", + "type": "bytes[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "paused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "grant", + "type": "string" + } + ], + "name": "permissionIdByGrant", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "permissionId", + "type": "uint256" + } + ], + "name": "permissions", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "string", + "name": "grant", + "type": "string" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "internalType": "struct IDataPermission.Permission", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "permissionsCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proxiableUUID", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "callerConfirmation", + "type": "address" + } + ], + "name": "renounceRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serverId", + "type": "address" + } + ], + "name": "servers", + "outputs": [ + { + "components": [ + { + "internalType": "string", + "name": "url", + "type": "string" + } + ], + "internalType": "struct IDataPermission.Server", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "adminRole", + "type": "bytes32" + } + ], + "name": "setRoleAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serverId", + "type": "address" + }, + { + "internalType": "string", + "name": "serverUrl", + "type": "string" + } + ], + "name": "trustServer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "address", + "name": "serverId", + "type": "address" + }, + { + "internalType": "string", + "name": "serverUrl", + "type": "string" + } + ], + "internalType": "struct IDataPermission.TrustServerInput", + "name": "trustServerInput", + "type": "tuple" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "name": "trustServerWithSignature", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "trustedForwarder", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "unpause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serverId", + "type": "address" + } + ], + "name": "untrustServer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "address", + "name": "serverId", + "type": "address" + } + ], + "internalType": "struct IDataPermission.UntrustServerInput", + "name": "untrustServerInput", + "type": "tuple" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "name": "untrustServerWithSignature", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "trustedForwarderAddress", + "type": "address" + } + ], + "name": "updateTrustedForwarder", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "userNonce", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "internalType": "uint256", + "name": "permissionIndex", + "type": "uint256" + } + ], + "name": "userPermissionIdsAt", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "userPermissionIdsLength", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "userPermissionIdsValues", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "internalType": "uint256", + "name": "serverIndex", + "type": "uint256" + } + ], + "name": "userServerIdsAt", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "userServerIdsLength", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "userServerIdsValues", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + } +] \ No newline at end of file diff --git a/abis/v5/DataRegistryImplementation.json b/abis/v5/DataRegistryImplementation.json new file mode 100644 index 0000000..b93e6d8 --- /dev/null +++ b/abis/v5/DataRegistryImplementation.json @@ -0,0 +1,1188 @@ +[ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "AccessControlBadConfirmation", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "neededRole", + "type": "bytes32" + } + ], + "name": "AccessControlUnauthorizedAccount", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + } + ], + "name": "AddressEmptyCode", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "ERC1967InvalidImplementation", + "type": "error" + }, + { + "inputs": [], + "name": "ERC1967NonPayable", + "type": "error" + }, + { + "inputs": [], + "name": "EnforcedPause", + "type": "error" + }, + { + "inputs": [], + "name": "ExpectedPause", + "type": "error" + }, + { + "inputs": [], + "name": "FailedInnerCall", + "type": "error" + }, + { + "inputs": [], + "name": "FileNotFound", + "type": "error" + }, + { + "inputs": [], + "name": "FileUrlAlreadyUsed", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidInitialization", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "schemaId", + "type": "uint256" + } + ], + "name": "InvalidSchemaId", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidUrl", + "type": "error" + }, + { + "inputs": [], + "name": "NoPermission", + "type": "error" + }, + { + "inputs": [], + "name": "NotFileOwner", + "type": "error" + }, + { + "inputs": [], + "name": "NotInitializing", + "type": "error" + }, + { + "inputs": [], + "name": "UUPSUnauthorizedCallContext", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "slot", + "type": "bytes32" + } + ], + "name": "UUPSUnsupportedProxiableUUID", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "fileId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "ownerAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "string", + "name": "url", + "type": "string" + } + ], + "name": "FileAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint64", + "name": "version", + "type": "uint64" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "fileId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "PermissionGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "fileId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "ownerAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "proofIndex", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "dlpId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "score", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "proofUrl", + "type": "string" + } + ], + "name": "ProofAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "fileId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "refinerId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "url", + "type": "string" + } + ], + "name": "RefinementAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "fileId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "refinerId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "url", + "type": "string" + } + ], + "name": "RefinementUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "previousAdminRole", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "newAdminRole", + "type": "bytes32" + } + ], + "name": "RoleAdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "inputs": [], + "name": "DEFAULT_ADMIN_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAINTAINER_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "REFINEMENT_SERVICE_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "UPGRADE_INTERFACE_VERSION", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "url", + "type": "string" + } + ], + "name": "addFile", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "fileId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "string", + "name": "key", + "type": "string" + } + ], + "name": "addFilePermission", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "url", + "type": "string" + }, + { + "internalType": "address", + "name": "ownerAddress", + "type": "address" + }, + { + "components": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "string", + "name": "key", + "type": "string" + } + ], + "internalType": "struct IDataRegistry.Permission[]", + "name": "permissions", + "type": "tuple[]" + } + ], + "name": "addFileWithPermissions", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "url", + "type": "string" + }, + { + "internalType": "address", + "name": "ownerAddress", + "type": "address" + }, + { + "components": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "string", + "name": "key", + "type": "string" + } + ], + "internalType": "struct IDataRegistry.Permission[]", + "name": "permissions", + "type": "tuple[]" + }, + { + "internalType": "uint256", + "name": "schemaId", + "type": "uint256" + } + ], + "name": "addFileWithPermissionsAndSchema", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "url", + "type": "string" + }, + { + "internalType": "uint256", + "name": "schemaId", + "type": "uint256" + } + ], + "name": "addFileWithSchema", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "fileId", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "score", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "dlpId", + "type": "uint256" + }, + { + "internalType": "string", + "name": "metadata", + "type": "string" + }, + { + "internalType": "string", + "name": "proofUrl", + "type": "string" + }, + { + "internalType": "string", + "name": "instruction", + "type": "string" + } + ], + "internalType": "struct IDataRegistry.ProofData", + "name": "data", + "type": "tuple" + } + ], + "internalType": "struct IDataRegistry.Proof", + "name": "proof", + "type": "tuple" + } + ], + "name": "addProof", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "fileId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "refinerId", + "type": "uint256" + }, + { + "internalType": "string", + "name": "url", + "type": "string" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "string", + "name": "key", + "type": "string" + } + ], + "name": "addRefinementWithPermission", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "dataRefinerRegistry", + "outputs": [ + { + "internalType": "contract IDataRefinerRegistry", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "url", + "type": "string" + } + ], + "name": "fileIdByUrl", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "fileId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "filePermissions", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "fileId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "name": "fileProofs", + "outputs": [ + { + "components": [ + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "score", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "dlpId", + "type": "uint256" + }, + { + "internalType": "string", + "name": "metadata", + "type": "string" + }, + { + "internalType": "string", + "name": "proofUrl", + "type": "string" + }, + { + "internalType": "string", + "name": "instruction", + "type": "string" + } + ], + "internalType": "struct IDataRegistry.ProofData", + "name": "data", + "type": "tuple" + } + ], + "internalType": "struct IDataRegistry.Proof", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "fileId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "refinerId", + "type": "uint256" + } + ], + "name": "fileRefinements", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "fileId", + "type": "uint256" + } + ], + "name": "files", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "address", + "name": "ownerAddress", + "type": "address" + }, + { + "internalType": "string", + "name": "url", + "type": "string" + }, + { + "internalType": "uint256", + "name": "addedAtBlock", + "type": "uint256" + } + ], + "internalType": "struct IDataRegistry.FileResponse", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "filesCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleAdmin", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRole", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "trustedForwarderAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "ownerAddress", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "forwarder", + "type": "address" + } + ], + "name": "isTrustedForwarder", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes[]", + "name": "data", + "type": "bytes[]" + } + ], + "name": "multicall", + "outputs": [ + { + "internalType": "bytes[]", + "name": "results", + "type": "bytes[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "paused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proxiableUUID", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "callerConfirmation", + "type": "address" + } + ], + "name": "renounceRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "adminRole", + "type": "bytes32" + } + ], + "name": "setRoleAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "trustedForwarder", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "unpause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IDataRefinerRegistry", + "name": "newDataRefinerRegistry", + "type": "address" + } + ], + "name": "updateDataRefinerRegistry", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "trustedForwarderAddress", + "type": "address" + } + ], + "name": "updateTrustedForwarder", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + } +] \ No newline at end of file From 821be09849147b5c796ff47131a22357dbcd2a7d Mon Sep 17 00:00:00 2001 From: Volod Date: Thu, 10 Jul 2025 10:30:22 -0400 Subject: [PATCH 02/22] feat: add File, Permission, and TrustedServer entities --- schema.graphql | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/schema.graphql b/schema.graphql index f44929d..013d2e9 100644 --- a/schema.graphql +++ b/schema.graphql @@ -1,6 +1,12 @@ type User @entity(immutable: false) { id: ID! fileContributions: [DataRegistryProof!] @derivedFrom(field: "user") + "All files owned by this user" + files: [File!]! @derivedFrom(field: "owner") + "All permissions granted by this user" + permissions: [Permission!]! @derivedFrom(field: "user") + "All servers trusted by this user" + trustedServers: [TrustedServer!]! @derivedFrom(field: "user") } type UserTotals @entity(immutable: false) { @@ -130,3 +136,52 @@ type DlpPerformance @entity(immutable: false) { createdTxHash: Bytes! createdAtBlock: BigInt! } + +type File @entity(immutable: false) { + "The unique ID of the file, equivalent to the on-chain fileId." + id: ID! + "The owner of the file." + owner: User! + "The URL where the file data is stored (e.g., IPFS)." + url: String! + "The schema ID associated with this file, if any." + schemaId: BigInt! + "The block number when the file was added." + addedAtBlock: BigInt! + "The timestamp when the file was added." + addedAtTimestamp: BigInt! + "The transaction hash of the file addition." + transactionHash: Bytes! +} + +type Permission @entity(immutable: false) { + "The unique ID of the permission, equivalent to the on-chain permissionId." + id: ID! + "The user who granted the permission." + user: User! + "The content identifier (e.g., IPFS URL) for the grant details." + grant: String! + "The nonce used for this permission grant." + nonce: BigInt! + "The signature provided by the user." + signature: Bytes! + "The block number when the permission was granted." + addedAtBlock: BigInt! + "The timestamp when the permission was granted." + addedAtTimestamp: BigInt! + "The transaction hash of the permission grant." + transactionHash: Bytes! +} + +type TrustedServer @entity(immutable: false) { + "Composite ID: userAddress-serverAddress" + id: ID! + "The user who trusts the server." + user: User! + "The server's address (ID)." + serverAddress: Bytes! + "The URL of the server." + serverUrl: String! + "Timestamp of when the trust was established." + trustedAt: BigInt! +} \ No newline at end of file From d0b110dfbb773d8c0a73b6f0dfead80c360d08e9 Mon Sep 17 00:00:00 2001 From: Volod Date: Thu, 10 Jul 2025 10:31:44 -0400 Subject: [PATCH 03/22] feat: Enable dataPermission handlers in build --- config/moksha.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/config/moksha.json b/config/moksha.json index 15ecd20..0f2a423 100644 --- a/config/moksha.json +++ b/config/moksha.json @@ -19,7 +19,8 @@ "vanaEpoch": true, "dlpPerformance": true, "queryEngine": true, - "dataRefinerRegistry": true + "dataRefinerRegistry": true, + "dataPermission": true } }, "initParams": { From b7408a2dd82728bdd34dc9759b298e0846a9bb6b Mon Sep 17 00:00:00 2001 From: Volod Date: Thu, 10 Jul 2025 10:40:44 -0400 Subject: [PATCH 04/22] feat: add DataPermission contract as data source --- subgraph.moksha.yaml | 54 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/subgraph.moksha.yaml b/subgraph.moksha.yaml index 50d3975..5544a43 100644 --- a/subgraph.moksha.yaml +++ b/subgraph.moksha.yaml @@ -219,4 +219,58 @@ dataSources: eventHandlers: - event: EpochDlpPerformancesSaved(indexed uint256,indexed uint256,uint256,uint256,uint256,uint256) handler: handleEpochDlpPerformancesSavedV5 + file: ./src/mapping.ts + + - kind: ethereum/contract + name: DataPermissionImplementation + network: moksha + source: + address: "0x3acB2023DF2617EFb61422BA0c8C6E97916961e0" + abi: DataPermissionImplementation + startBlock: 3425120 + mapping: + kind: ethereum/events + apiVersion: 0.0.6 + language: wasm/assemblyscript + entities: + - Permission + - User + - TrustedServer + abis: + - name: DataPermissionImplementation + file: ./abis/v5/DataPermissionImplementation.json + callHandlers: + - function: permissions(uint256) + handler: handleGetPermission + eventHandlers: + - event: PermissionAdded(indexed uint256,indexed address,string) + handler: handlePermissionAdded + - event: ServerTrusted(indexed address,indexed address,string) + handler: handleServerTrusted + - event: ServerUntrusted(indexed address,indexed address) + handler: handleServerUntrusted + file: ./src/mapping.ts + + - kind: ethereum/contract + name: DataRegistryImplementationV5 + network: mainnet + source: + address: "0x8C8788f98385F6ba1adD4234e551ABba0f82Cb7C" + abi: DataRegistryImplementationV5 + startBlock: 3425120 + mapping: + kind: ethereum/events + apiVersion: 0.0.6 + language: wasm/assemblyscript + entities: + - EpochReference + - DataRegistryProof + abis: + - name: DataRegistryImplementationV5 + file: ./abis/v5/DataRegistryImplementation.json + eventHandlers: + - event: FileAdded(indexed uint256,indexed address,string) + handler: handleFileAddedV3 + - event: ProofAdded(indexed uint256,indexed address,uint256,indexed uint256,uint256,string) + handler: handleDataRegistryProofAddedV3 file: ./src/mapping.ts \ No newline at end of file From a9870d1efafe06edab70cf34148502341df38b3d Mon Sep 17 00:00:00 2001 From: Volod Date: Thu, 10 Jul 2025 10:45:45 -0400 Subject: [PATCH 05/22] feat: index file entity from V1-V3 FileAdded events --- src/lib/contract/v1/data-registry.ts | 24 ++++++++++++++++++++---- src/lib/contract/v2/data-registry.ts | 21 +++++++++++++++++++-- src/lib/contract/v3/data-registry.ts | 24 +++++++++++++++++++----- 3 files changed, 58 insertions(+), 11 deletions(-) diff --git a/src/lib/contract/v1/data-registry.ts b/src/lib/contract/v1/data-registry.ts index 03530cc..ef524f7 100644 --- a/src/lib/contract/v1/data-registry.ts +++ b/src/lib/contract/v1/data-registry.ts @@ -2,7 +2,7 @@ import { BigInt as GraphBigInt, log } from "@graphprotocol/graph-ts"; import { DataRegistryProof, - EpochReference, + File, FileOwner, } from "../../../../generated/schema"; @@ -10,19 +10,35 @@ import { FileAdded as FileAddedEvent, ProofAdded as FileProofAdded, } from "../../../../generated/DataRegistryImplementationV1/DataRegistryImplementationV1"; -import { EPOCH_REFERENCE_ID_CURRENT } from "../../entity/epoch"; +import { getEpochForBlock } from "../../entity/epoch"; // FIX: Added getEpochForBlock and EPOCH_REFERENCE_ID_CURRENT here import { getOrCreateUserTotals, getUserTotalsId, } from "../../entity/usertotals"; import { getOrCreateTotals, TOTALS_ID_GLOBAL } from "../../entity/totals"; -import { getEpochForBlock } from "../../entity/epoch"; +import { getOrCreateUser } from "../shared"; export function handleFileAddedV1(event: FileAddedEvent): void { log.info("Handling DataRegistry FileAdded with transaction hash: {}", [ event.transaction.hash.toHex(), ]); + // Create user entity if it doesn't exist + const user = getOrCreateUser(event.params.ownerAddress.toHex()); + + // Create new File entity + const file = new File(event.params.fileId.toString()); + file.owner = user.id; + file.url = event.params.url; + file.addedAtBlock = event.block.number; + file.addedAtTimestamp = event.block.timestamp; + file.transactionHash = event.transaction.hash; + + // V1 of the contract does not support schemaId, so we set it to 0 + file.schemaId = GraphBigInt.fromI32(0); + + file.save(); + const ownership = new FileOwner(event.params.fileId.toString()); ownership.ownerAddress = event.params.ownerAddress; ownership.save(); @@ -90,4 +106,4 @@ export function handleDataRegistryProofAddedV1(event: FileProofAdded): void { ); } totals.save(); -} +} \ No newline at end of file diff --git a/src/lib/contract/v2/data-registry.ts b/src/lib/contract/v2/data-registry.ts index b45f75b..d86e59d 100644 --- a/src/lib/contract/v2/data-registry.ts +++ b/src/lib/contract/v2/data-registry.ts @@ -2,6 +2,7 @@ import { BigInt as GraphBigInt, log } from "@graphprotocol/graph-ts"; import { DataRegistryProof, + File, FileOwner, } from "../../../../generated/schema"; @@ -20,13 +21,29 @@ import { TOTALS_ID_GLOBAL, } from "../../entity/totals"; import { getEpochForBlock } from "../../entity/epoch"; -import {getOrCreateDlp} from "../shared"; +import {getOrCreateDlp, getOrCreateUser} from "../shared"; export function handleFileAddedV2(event: FileAddedEvent): void { log.info("Handling DataRegistry FileAdded with transaction hash: {}", [ event.transaction.hash.toHex(), ]); + // Create user entity if it doesn't exist + const user = getOrCreateUser(event.params.ownerAddress.toHex()); + + // Create new File entity + const file = new File(event.params.fileId.toString()); + file.owner = user.id; + file.url = event.params.url; + file.addedAtBlock = event.block.number; + file.addedAtTimestamp = event.block.timestamp; + file.transactionHash = event.transaction.hash; + + // V2 of the contract does not support schemaId, so we set it to 0 + file.schemaId = GraphBigInt.fromI32(0); + + file.save(); + const ownership = new FileOwner(event.params.fileId.toString()); ownership.ownerAddress = event.params.ownerAddress; ownership.save(); @@ -121,4 +138,4 @@ export function handleDataRegistryProofAddedV2(event: FileProofAdded): void { ); } dlpTotals.save(); -} +} \ No newline at end of file diff --git a/src/lib/contract/v3/data-registry.ts b/src/lib/contract/v3/data-registry.ts index 85fa1e8..67fe726 100644 --- a/src/lib/contract/v3/data-registry.ts +++ b/src/lib/contract/v3/data-registry.ts @@ -2,8 +2,7 @@ import { BigInt as GraphBigInt, log } from "@graphprotocol/graph-ts"; import { DataRegistryProof, - Dlp, - EpochReference, + File, FileOwner, } from "../../../../generated/schema"; @@ -11,7 +10,7 @@ import { FileAdded as FileAddedEvent, ProofAdded as FileProofAdded, } from "../../../../generated/DataRegistryImplementationV3/DataRegistryImplementationV3"; -import { EPOCH_REFERENCE_ID_CURRENT } from "../../entity/epoch"; +import { getEpochForBlock } from "../../entity/epoch"; import { getOrCreateUserTotals, getUserTotalsId, @@ -23,13 +22,28 @@ import { TOTALS_ID_GLOBAL, } from "../../entity/totals"; import {getOrCreateDlp, getOrCreateUser} from "../shared"; -import { getEpochForBlock } from "../../entity/epoch"; export function handleFileAddedV3(event: FileAddedEvent): void { log.info("Handling DataRegistry FileAdded with transaction hash: {}", [ event.transaction.hash.toHex(), ]); + // Create user entity if it doesn't exist + const user = getOrCreateUser(event.params.ownerAddress.toHex()); + + // Create new File entity + const file = new File(event.params.fileId.toString()); + file.owner = user.id; + file.url = event.params.url; + file.addedAtBlock = event.block.number; + file.addedAtTimestamp = event.block.timestamp; + file.transactionHash = event.transaction.hash; + + // V3 of the contract does not support schemaId, so we set it to 0 + file.schemaId = GraphBigInt.fromI32(0); + + file.save(); + const ownership = new FileOwner(event.params.fileId.toString()); ownership.ownerAddress = event.params.ownerAddress; ownership.save(); @@ -113,4 +127,4 @@ export function handleDataRegistryProofAddedV3(event: FileProofAdded): void { ); } dlpTotals.save(); -} +} \ No newline at end of file From cb2e36042b09f84d050bdb7a196969db462b01d1 Mon Sep 17 00:00:00 2001 From: Volod Date: Thu, 10 Jul 2025 10:46:12 -0400 Subject: [PATCH 06/22] feat: add conditional export for permission handlers --- src/mapping.ts.template | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/mapping.ts.template b/src/mapping.ts.template index 5d27411..ed2dfbc 100644 --- a/src/mapping.ts.template +++ b/src/mapping.ts.template @@ -63,3 +63,6 @@ export * from "./lib/contract/v5/vana-epoch"; {{#includes.v5.dlpPerformance}} export * from "./lib/contract/v5/dlp-performance"; {{/includes.v5.dlpPerformance}} +{{#includes.v5.dataPermission}} +export * from "./lib/contract/v5/data-permission"; +{{/includes.v5.dataPermission}} \ No newline at end of file From 1416bf02cc919745b20d0f80bac0f1a2b18d6475 Mon Sep 17 00:00:00 2001 From: Volod Date: Thu, 10 Jul 2025 11:02:30 -0400 Subject: [PATCH 07/22] feat: add data permission handler to vcs --- src/lib/contract/v5/data-permission.ts | 82 ++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 src/lib/contract/v5/data-permission.ts diff --git a/src/lib/contract/v5/data-permission.ts b/src/lib/contract/v5/data-permission.ts new file mode 100644 index 0000000..f7aaddb --- /dev/null +++ b/src/lib/contract/v5/data-permission.ts @@ -0,0 +1,82 @@ +import { log, store, BigInt, Bytes } from "@graphprotocol/graph-ts"; +import { + PermissionAdded, + ServerTrusted, + ServerUntrusted, + DataPermissionImplementation, +} from "../../../../generated/DataPermissionImplementation/DataPermissionImplementation"; +import { Permission, TrustedServer } from "../../../../generated/schema"; +import { getOrCreateUser } from "../shared"; + +export function handlePermissionAdded(event: PermissionAdded): void { + log.info("Handling PermissionAdded with transaction hash: {}", [ + event.transaction.hash.toHexString(), + ]); + + const user = getOrCreateUser(event.params.user.toHex()); + const permissionId = event.params.permissionId; + + const permission = new Permission(permissionId.toString()); + permission.user = user.id; + permission.grant = event.params.grant; + permission.addedAtBlock = event.block.number; + permission.addedAtTimestamp = event.block.timestamp; + permission.transactionHash = event.transaction.hash; + + // Since nonce and signature are not in the event, we must call the contract. + const contract = DataPermissionImplementation.bind(event.address); + const permissionData = contract.try_permissions(permissionId); + + if (!permissionData.reverted) { + // FIX: Access properties directly instead of using getters. + permission.nonce = permissionData.value.nonce; + permission.signature = permissionData.value.signature; + } else { + log.warning("Could not get permission data for id {}. Nonce and signature will be zero.", [permissionId.toString()]); + permission.nonce = BigInt.zero(); + // FIX: Use an empty Bytes array for an empty signature. + permission.signature = new Bytes(0); + } + + permission.save(); +} + +export function handleServerTrusted(event: ServerTrusted): void { + log.info("Handling ServerTrusted for user {} and server {}", [ + event.params.user.toHex(), + event.params.serverId.toHex(), + ]); + + const user = getOrCreateUser(event.params.user.toHex()); + const serverId = event.params.serverId; + const compositeId = user.id + "-" + serverId.toHex(); + + let trustedServer = TrustedServer.load(compositeId); + if (trustedServer == null) { + trustedServer = new TrustedServer(compositeId); + trustedServer.user = user.id; + trustedServer.serverAddress = serverId; + } + + trustedServer.serverUrl = event.params.serverUrl; + trustedServer.trustedAt = event.block.timestamp; + trustedServer.save(); +} + +export function handleServerUntrusted(event: ServerUntrusted): void { + log.info("Handling ServerUntrusted for user {} and server {}", [ + event.params.user.toHex(), + event.params.serverId.toHex(), + ]); + + const userId = event.params.user.toHex(); + const serverId = event.params.serverId.toHex(); + const compositeId = userId + "-" + serverId; + + const trustedServer = TrustedServer.load(compositeId); + if (trustedServer != null) { + store.remove("TrustedServer", compositeId); + } else { + log.warning("Attempted to untrust a server that was not found: {}", [compositeId]); + } +} \ No newline at end of file From c502ba5f90fff6c46089df7c6e1f0a2dff4d9722 Mon Sep 17 00:00:00 2001 From: Volod Date: Thu, 10 Jul 2025 11:03:11 -0400 Subject: [PATCH 08/22] fix: remove redundant call handler for DataPermissionImplementation --- subgraph.moksha.yaml | 3 --- 1 file changed, 3 deletions(-) diff --git a/subgraph.moksha.yaml b/subgraph.moksha.yaml index 5544a43..d0a9801 100644 --- a/subgraph.moksha.yaml +++ b/subgraph.moksha.yaml @@ -239,9 +239,6 @@ dataSources: abis: - name: DataPermissionImplementation file: ./abis/v5/DataPermissionImplementation.json - callHandlers: - - function: permissions(uint256) - handler: handleGetPermission eventHandlers: - event: PermissionAdded(indexed uint256,indexed address,string) handler: handlePermissionAdded From 248c686114def6e53eca40dfaf69145d919b9b7d Mon Sep 17 00:00:00 2001 From: Volod Date: Thu, 10 Jul 2025 11:06:01 -0400 Subject: [PATCH 09/22] fix: typo --- subgraph.moksha.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subgraph.moksha.yaml b/subgraph.moksha.yaml index d0a9801..76a8581 100644 --- a/subgraph.moksha.yaml +++ b/subgraph.moksha.yaml @@ -250,7 +250,7 @@ dataSources: - kind: ethereum/contract name: DataRegistryImplementationV5 - network: mainnet + network: moksha source: address: "0x8C8788f98385F6ba1adD4234e551ABba0f82Cb7C" abi: DataRegistryImplementationV5 From c22f7efbac60a1c90edbaa4f7a6779531f06b2aa Mon Sep 17 00:00:00 2001 From: Volod Date: Thu, 10 Jul 2025 11:25:57 -0400 Subject: [PATCH 10/22] fix: lint --- schema.graphql | 2 +- src/lib/contract/shared.ts | 4 ++-- src/lib/contract/v1/data-registry.ts | 2 +- src/lib/contract/v2/data-registry.ts | 4 ++-- src/lib/contract/v3/data-registry.ts | 4 ++-- src/lib/contract/v5/data-permission.ts | 11 ++++++++--- src/lib/contract/v5/dlp-registry.ts | 2 +- 7 files changed, 17 insertions(+), 12 deletions(-) diff --git a/schema.graphql b/schema.graphql index 013d2e9..3b12a31 100644 --- a/schema.graphql +++ b/schema.graphql @@ -184,4 +184,4 @@ type TrustedServer @entity(immutable: false) { serverUrl: String! "Timestamp of when the trust was established." trustedAt: BigInt! -} \ No newline at end of file +} diff --git a/src/lib/contract/shared.ts b/src/lib/contract/shared.ts index 71358f3..38883df 100644 --- a/src/lib/contract/shared.ts +++ b/src/lib/contract/shared.ts @@ -1,5 +1,5 @@ -import {Dlp, User} from "../../../generated/schema"; -import {getOrCreateTotals, getTotalsIdDlp} from "../entity/totals"; +import { Dlp, User } from "../../../generated/schema"; +import { getOrCreateTotals, getTotalsIdDlp } from "../entity/totals"; export function getOrCreateUser(userId: string): User { let user = User.load(userId); diff --git a/src/lib/contract/v1/data-registry.ts b/src/lib/contract/v1/data-registry.ts index ef524f7..79d814c 100644 --- a/src/lib/contract/v1/data-registry.ts +++ b/src/lib/contract/v1/data-registry.ts @@ -106,4 +106,4 @@ export function handleDataRegistryProofAddedV1(event: FileProofAdded): void { ); } totals.save(); -} \ No newline at end of file +} diff --git a/src/lib/contract/v2/data-registry.ts b/src/lib/contract/v2/data-registry.ts index d86e59d..245a5be 100644 --- a/src/lib/contract/v2/data-registry.ts +++ b/src/lib/contract/v2/data-registry.ts @@ -21,7 +21,7 @@ import { TOTALS_ID_GLOBAL, } from "../../entity/totals"; import { getEpochForBlock } from "../../entity/epoch"; -import {getOrCreateDlp, getOrCreateUser} from "../shared"; +import { getOrCreateDlp, getOrCreateUser } from "../shared"; export function handleFileAddedV2(event: FileAddedEvent): void { log.info("Handling DataRegistry FileAdded with transaction hash: {}", [ @@ -138,4 +138,4 @@ export function handleDataRegistryProofAddedV2(event: FileProofAdded): void { ); } dlpTotals.save(); -} \ No newline at end of file +} diff --git a/src/lib/contract/v3/data-registry.ts b/src/lib/contract/v3/data-registry.ts index 67fe726..a9df8d7 100644 --- a/src/lib/contract/v3/data-registry.ts +++ b/src/lib/contract/v3/data-registry.ts @@ -21,7 +21,7 @@ import { getTotalsIdDlp, TOTALS_ID_GLOBAL, } from "../../entity/totals"; -import {getOrCreateDlp, getOrCreateUser} from "../shared"; +import { getOrCreateDlp, getOrCreateUser } from "../shared"; export function handleFileAddedV3(event: FileAddedEvent): void { log.info("Handling DataRegistry FileAdded with transaction hash: {}", [ @@ -127,4 +127,4 @@ export function handleDataRegistryProofAddedV3(event: FileProofAdded): void { ); } dlpTotals.save(); -} \ No newline at end of file +} diff --git a/src/lib/contract/v5/data-permission.ts b/src/lib/contract/v5/data-permission.ts index f7aaddb..d069f44 100644 --- a/src/lib/contract/v5/data-permission.ts +++ b/src/lib/contract/v5/data-permission.ts @@ -32,7 +32,10 @@ export function handlePermissionAdded(event: PermissionAdded): void { permission.nonce = permissionData.value.nonce; permission.signature = permissionData.value.signature; } else { - log.warning("Could not get permission data for id {}. Nonce and signature will be zero.", [permissionId.toString()]); + log.warning( + "Could not get permission data for id {}. Nonce and signature will be zero.", + [permissionId.toString()], + ); permission.nonce = BigInt.zero(); // FIX: Use an empty Bytes array for an empty signature. permission.signature = new Bytes(0); @@ -77,6 +80,8 @@ export function handleServerUntrusted(event: ServerUntrusted): void { if (trustedServer != null) { store.remove("TrustedServer", compositeId); } else { - log.warning("Attempted to untrust a server that was not found: {}", [compositeId]); + log.warning("Attempted to untrust a server that was not found: {}", [ + compositeId, + ]); } -} \ No newline at end of file +} diff --git a/src/lib/contract/v5/dlp-registry.ts b/src/lib/contract/v5/dlp-registry.ts index 64a4f0c..875c8d8 100644 --- a/src/lib/contract/v5/dlp-registry.ts +++ b/src/lib/contract/v5/dlp-registry.ts @@ -12,7 +12,7 @@ import { Dlp } from "../../../../generated/schema"; import { getTotalsIdDlp } from "../../entity/totals/constants"; import { getOrCreateDlpList } from "../../../../src/lib/entity/dlp-list"; import { getOrCreateTotals } from "../../entity/totals"; -import {getOrCreateDlp, getOrCreateUser} from "../shared"; +import { getOrCreateDlp, getOrCreateUser } from "../shared"; // Mirrored from DLPRegistry.IDLPRegistry.DlpStatus enum dlpStatus { From b9ba605ad69adfd46ba691ca6f53e51c3b0e22d5 Mon Sep 17 00:00:00 2001 From: Volod Date: Thu, 10 Jul 2025 11:33:44 -0400 Subject: [PATCH 11/22] fix: lint --- src/lib/contract/v5/data-permission.ts | 13 +++++++++---- src/lib/contract/v5/dlp-registry.ts | 19 ++++++++----------- src/lib/contract/v5/vana-epoch.ts | 9 +++------ src/lib/entity/epoch/epoch-reference.ts | 13 +++++++------ 4 files changed, 27 insertions(+), 27 deletions(-) diff --git a/src/lib/contract/v5/data-permission.ts b/src/lib/contract/v5/data-permission.ts index d069f44..440c429 100644 --- a/src/lib/contract/v5/data-permission.ts +++ b/src/lib/contract/v5/data-permission.ts @@ -1,4 +1,9 @@ -import { log, store, BigInt, Bytes } from "@graphprotocol/graph-ts"; +import { + log, + store, + BigInt as GraphBigInt, + Bytes, +} from "@graphprotocol/graph-ts"; import { PermissionAdded, ServerTrusted, @@ -36,7 +41,7 @@ export function handlePermissionAdded(event: PermissionAdded): void { "Could not get permission data for id {}. Nonce and signature will be zero.", [permissionId.toString()], ); - permission.nonce = BigInt.zero(); + permission.nonce = GraphBigInt.zero(); // FIX: Use an empty Bytes array for an empty signature. permission.signature = new Bytes(0); } @@ -52,7 +57,7 @@ export function handleServerTrusted(event: ServerTrusted): void { const user = getOrCreateUser(event.params.user.toHex()); const serverId = event.params.serverId; - const compositeId = user.id + "-" + serverId.toHex(); + const compositeId = `${user.id}-${serverId.toHex()}`; let trustedServer = TrustedServer.load(compositeId); if (trustedServer == null) { @@ -74,7 +79,7 @@ export function handleServerUntrusted(event: ServerUntrusted): void { const userId = event.params.user.toHex(); const serverId = event.params.serverId.toHex(); - const compositeId = userId + "-" + serverId; + const compositeId = `${userId}-${serverId}`; const trustedServer = TrustedServer.load(compositeId); if (trustedServer != null) { diff --git a/src/lib/contract/v5/dlp-registry.ts b/src/lib/contract/v5/dlp-registry.ts index 875c8d8..91feef8 100644 --- a/src/lib/contract/v5/dlp-registry.ts +++ b/src/lib/contract/v5/dlp-registry.ts @@ -1,4 +1,4 @@ -import { BigInt, log } from "@graphprotocol/graph-ts"; +import { BigInt as GraphBigInt, log } from "@graphprotocol/graph-ts"; import { DlpRegistered, DlpUpdated, @@ -9,9 +9,7 @@ import { } from "../../../../generated/DLPRegistryImplementationV5/DLPRegistryImplementationV5"; import { Dlp } from "../../../../generated/schema"; -import { getTotalsIdDlp } from "../../entity/totals/constants"; import { getOrCreateDlpList } from "../../../../src/lib/entity/dlp-list"; -import { getOrCreateTotals } from "../../entity/totals"; import { getOrCreateDlp, getOrCreateUser } from "../shared"; // Mirrored from DLPRegistry.IDLPRegistry.DlpStatus @@ -46,13 +44,13 @@ export function handleDlpRegisteredV5(event: DlpRegistered): void { dlp.createdAt = event.block.timestamp; dlp.createdTxHash = event.transaction.hash; dlp.createdAtBlock = event.block.number; - dlp.status = BigInt.fromI32(dlpStatus.REGISTERED); + dlp.status = GraphBigInt.fromI32(dlpStatus.REGISTERED); // New field in v5 dlp.isVerified = false; // Keep staking fields for backward compatibility but set to zero - dlp.performanceRating = BigInt.zero(); + dlp.performanceRating = GraphBigInt.zero(); dlp.save(); @@ -102,7 +100,7 @@ export function handleDlpStatusUpdatedV5(event: DlpStatusUpdated): void { if (dlp != null) { const newStatus = event.params.newStatus; - dlp.status = BigInt.fromI32(newStatus); + dlp.status = GraphBigInt.fromI32(newStatus); // Track eligibility transitions if (newStatus === dlpStatus.ELIGIBLE) { @@ -142,9 +140,9 @@ export function handleDlpVerificationUpdatedV5( } if (isEligible) { - dlp.status = BigInt.fromI32(dlpStatus.ELIGIBLE); + dlp.status = GraphBigInt.fromI32(dlpStatus.ELIGIBLE); } else { - dlp.status = BigInt.fromI32(dlpStatus.REGISTERED); + dlp.status = GraphBigInt.fromI32(dlpStatus.REGISTERED); } dlp.save(); } else { @@ -172,9 +170,9 @@ export function handleDlpTokenUpdatedV5(event: DlpTokenUpdated): void { } if (isEligible) { - dlp.status = BigInt.fromI32(dlpStatus.ELIGIBLE); + dlp.status = GraphBigInt.fromI32(dlpStatus.ELIGIBLE); } else { - dlp.status = BigInt.fromI32(dlpStatus.REGISTERED); + dlp.status = GraphBigInt.fromI32(dlpStatus.REGISTERED); } dlp.save(); } @@ -185,5 +183,4 @@ export function handleDlpRegistrationDepositAmountUpdatedV5( log.info("handleDlpRegistrationDepositAmountUpdatedV5: {}", [ event.transaction.hash.toHexString(), ]); - // No state changes needed for deposit amount updates } diff --git a/src/lib/contract/v5/vana-epoch.ts b/src/lib/contract/v5/vana-epoch.ts index 9366a19..a1f98de 100644 --- a/src/lib/contract/v5/vana-epoch.ts +++ b/src/lib/contract/v5/vana-epoch.ts @@ -1,4 +1,4 @@ -import { BigInt, log } from "@graphprotocol/graph-ts"; +import { log } from "@graphprotocol/graph-ts"; import { EpochCreated, EpochDlpRewardAdded, @@ -6,12 +6,9 @@ import { EpochRewardAmountUpdated, EpochSizeUpdated, } from "../../../../generated/VanaEpochImplementationV5/VanaEpochImplementationV5"; -import { Epoch, EpochReference } from "../../../../generated/schema"; +import { Epoch } from "../../../../generated/schema"; import { getOrCreateCurrentParams } from "../../entity/params"; -import { - EPOCH_REFERENCE_ID_CURRENT, - saveCurrentEpochReference, -} from "../../entity/epoch"; +import { saveCurrentEpochReference } from "../../entity/epoch"; export function handleEpochCreatedV5(event: EpochCreated): void { log.info("handleEpochCreatedV5: {}", [event.transaction.hash.toHexString()]); diff --git a/src/lib/entity/epoch/epoch-reference.ts b/src/lib/entity/epoch/epoch-reference.ts index 6a2a4b0..bde29cf 100644 --- a/src/lib/entity/epoch/epoch-reference.ts +++ b/src/lib/entity/epoch/epoch-reference.ts @@ -1,4 +1,4 @@ -import { BigInt, log } from "@graphprotocol/graph-ts"; +import { BigInt as GraphBigInt, log } from "@graphprotocol/graph-ts"; import { Epoch, EpochReference } from "../../../../generated/schema"; import { EPOCH_REFERENCE_ID_CURRENT } from "./constants"; import { epochRanges } from "../../../mapping"; @@ -24,7 +24,7 @@ export function saveCurrentEpochReference(newEpochId: string): EpochReference { return currentEpoch; } -export function getEpochForBlock(blockNumber: BigInt): string { +export function getEpochForBlock(blockNumber: GraphBigInt): string { const currentEpochRef = getCurrentEpochReference(); if (!currentEpochRef || !currentEpochRef.epoch) { return getEpochFromRanges(blockNumber); @@ -35,15 +35,15 @@ export function getEpochForBlock(blockNumber: BigInt): string { return getEpochFromRanges(blockNumber); } - if (currentEpoch.endBlock.le(BigInt.zero())) { + if (currentEpoch.endBlock.le(GraphBigInt.zero())) { return currentEpoch.id; } // If the current epoch is in the past, we need to use the next epoch if (blockNumber.gt(currentEpoch.endBlock)) { // Get the next epoch by incrementing the current epoch ID - const nextEpochId = BigInt.fromString(currentEpoch.id) - .plus(BigInt.fromI32(1)) + const nextEpochId = GraphBigInt.fromString(currentEpoch.id) + .plus(GraphBigInt.fromI32(1)) .toString(); const nextEpoch = Epoch.load(nextEpochId); if (nextEpoch) { @@ -56,7 +56,8 @@ export function getEpochForBlock(blockNumber: BigInt): string { return currentEpoch.id; } -function getEpochFromRanges(blockNumber: BigInt): string { +function getEpochFromRanges(blockNumber: GraphBigInt): string { + // @ts-ignore const blockNumberInt = Number.parseInt(blockNumber.toString()); for (let i = 0; i < epochRanges.length; i++) { From 89fd1f7f8918cd4feb581ff070d57b5d829a6acd Mon Sep 17 00:00:00 2001 From: Volod Date: Thu, 10 Jul 2025 11:39:40 -0400 Subject: [PATCH 12/22] feat: add the relevant changes for the other subgraph yaml files --- subgraph.vana-moksha.yaml | 51 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/subgraph.vana-moksha.yaml b/subgraph.vana-moksha.yaml index a11787f..c9353dd 100644 --- a/subgraph.vana-moksha.yaml +++ b/subgraph.vana-moksha.yaml @@ -219,4 +219,55 @@ dataSources: eventHandlers: - event: EpochDlpPerformancesSaved(indexed uint256,indexed uint256,uint256,uint256,uint256,uint256) handler: handleEpochDlpPerformancesSavedV5 + file: ./src/mapping.ts + + - kind: ethereum/contract + name: DataPermissionImplementation + network: vana-moksha + source: + address: "0x3acB2023DF2617EFb61422BA0c8C6E97916961e0" + abi: DataPermissionImplementation + startBlock: 3425120 + mapping: + kind: ethereum/events + apiVersion: 0.0.6 + language: wasm/assemblyscript + entities: + - Permission + - User + - TrustedServer + abis: + - name: DataPermissionImplementation + file: ./abis/v5/DataPermissionImplementation.json + eventHandlers: + - event: PermissionAdded(indexed uint256,indexed address,string) + handler: handlePermissionAdded + - event: ServerTrusted(indexed address,indexed address,string) + handler: handleServerTrusted + - event: ServerUntrusted(indexed address,indexed address) + handler: handleServerUntrusted + file: ./src/mapping.ts + + - kind: ethereum/contract + name: DataRegistryImplementationV5 + network: vana-moksha + source: + address: "0x8C8788f98385F6ba1adD4234e551ABba0f82Cb7C" + abi: DataRegistryImplementationV5 + startBlock: 3425120 + mapping: + kind: ethereum/events + apiVersion: 0.0.6 + language: wasm/assemblyscript + entities: + - EpochReference + - DataRegistryProof + abis: + - name: DataRegistryImplementationV5 + file: ./abis/v5/DataRegistryImplementation.json + eventHandlers: + - event: FileAdded(indexed uint256,indexed address,string) + handler: handleFileAddedV3 + - event: ProofAdded(indexed uint256,indexed address,uint256,indexed uint256,uint256,string) + handler: handleDataRegistryProofAddedV3 file: ./src/mapping.ts \ No newline at end of file From 67d3b26984a7a2982dbcd3a4a24d7b6a2ecf7d91 Mon Sep 17 00:00:00 2001 From: Volod Date: Thu, 10 Jul 2025 12:53:50 -0400 Subject: [PATCH 13/22] feat: add tests --- tests/unit/contract/v1/data-registry.test.ts | 58 +++++++++++++++++++ .../contract/v1/utils/data-registry-events.ts | 28 +++++++++ 2 files changed, 86 insertions(+) create mode 100644 tests/unit/contract/v1/data-registry.test.ts create mode 100644 tests/unit/contract/v1/utils/data-registry-events.ts diff --git a/tests/unit/contract/v1/data-registry.test.ts b/tests/unit/contract/v1/data-registry.test.ts new file mode 100644 index 0000000..bfeb5af --- /dev/null +++ b/tests/unit/contract/v1/data-registry.test.ts @@ -0,0 +1,58 @@ +import { + assert, + beforeEach, + clearStore, + describe, + test, +} from "matchstick-as/assembly/index"; +import { BigInt as GraphBigInt } from "@graphprotocol/graph-ts"; +import { handleFileAddedV1 } from "../../../../src/lib/contract/v1/data-registry"; +import { createFileAddedEvent } from "./utils/data-registry-events"; + +// Hook to clear the store before each test, ensuring test isolation +beforeEach(() => { + clearStore(); +}); + +describe("handleFileAddedV1", () => { + test("creates both a File and a FileOwner entity", () => { + // 1. ARRANGE: Set up test data and create the mock event + const fileId = 1; + const ownerAddress = "0x1234567890123456789012345678901234567890"; + const url = "ipfs://Qm..."; + + const fileAddedEvent = createFileAddedEvent(fileId, ownerAddress, url); + + // 2. ACT: Call the handler function with the mock event + handleFileAddedV1(fileAddedEvent); + + // 3. ASSERT: Check that the store is in the correct state + + // --- Assert the NEW functionality --- + assert.entityCount("File", 1); + assert.fieldEquals("File", fileId.toString(), "id", fileId.toString()); + assert.fieldEquals("File", fileId.toString(), "owner", ownerAddress); + assert.fieldEquals("File", fileId.toString(), "url", url); + assert.fieldEquals("File", fileId.toString(), "schemaId", "0"); // Important check for V1 + assert.fieldEquals( + "File", + fileId.toString(), + "transactionHash", + fileAddedEvent.transaction.hash.toHexString(), + ); + + // Also check that the associated User was created + assert.entityCount("User", 1); + assert.fieldEquals("User", ownerAddress, "id", ownerAddress); + + // --- Assert the ORIGINAL functionality (prevents regression) --- + assert.entityCount("FileOwner", 1); + assert.fieldEquals("FileOwner", fileId.toString(), "id", fileId.toString()); + assert.fieldEquals( + "FileOwner", + fileId.toString(), + "ownerAddress", + ownerAddress, + ); + }); +}); diff --git a/tests/unit/contract/v1/utils/data-registry-events.ts b/tests/unit/contract/v1/utils/data-registry-events.ts new file mode 100644 index 0000000..8e8a3fd --- /dev/null +++ b/tests/unit/contract/v1/utils/data-registry-events.ts @@ -0,0 +1,28 @@ +import { Address, ethereum } from "@graphprotocol/graph-ts"; +import { newMockEvent } from "matchstick-as/assembly/index"; +import { FileAdded as FileAddedEvent } from "../../../../../generated/DataRegistryImplementationV1/DataRegistryImplementationV1"; + +export function createFileAddedEvent( + fileId: i32, + ownerAddress: string, + url: string, +): FileAddedEvent { + const normalizedAddr = ownerAddress.toLowerCase(); + const fileAddedEvent = changetype(newMockEvent()); + fileAddedEvent.parameters = new Array(); + + fileAddedEvent.parameters.push( + new ethereum.EventParam("fileId", ethereum.Value.fromI32(fileId)), + ); + fileAddedEvent.parameters.push( + new ethereum.EventParam( + "ownerAddress", + ethereum.Value.fromAddress(Address.fromString(normalizedAddr)), + ), + ); + fileAddedEvent.parameters.push( + new ethereum.EventParam("url", ethereum.Value.fromString(url)), + ); + + return fileAddedEvent; +} From 5ea688efd12b6f114ab1fbac5ba139e6afc84b38 Mon Sep 17 00:00:00 2001 From: Volod Date: Thu, 10 Jul 2025 12:53:58 -0400 Subject: [PATCH 14/22] feat: update existing tests --- src/lib/contract/v2/data-registry.ts | 14 ++++++++++---- src/lib/contract/v3/data-registry.ts | 16 +++++++++++----- src/lib/contract/v5/dlp-registry.ts | 11 +++++++++-- 3 files changed, 30 insertions(+), 11 deletions(-) diff --git a/src/lib/contract/v2/data-registry.ts b/src/lib/contract/v2/data-registry.ts index 245a5be..bc846a5 100644 --- a/src/lib/contract/v2/data-registry.ts +++ b/src/lib/contract/v2/data-registry.ts @@ -4,6 +4,7 @@ import { DataRegistryProof, File, FileOwner, + Dlp, } from "../../../../generated/schema"; import { @@ -21,7 +22,7 @@ import { TOTALS_ID_GLOBAL, } from "../../entity/totals"; import { getEpochForBlock } from "../../entity/epoch"; -import { getOrCreateDlp, getOrCreateUser } from "../shared"; +import { getOrCreateUser } from "../shared"; export function handleFileAddedV2(event: FileAddedEvent): void { log.info("Handling DataRegistry FileAdded with transaction hash: {}", [ @@ -56,13 +57,18 @@ export function handleDataRegistryProofAddedV2(event: FileProofAdded): void { // Get epoch for the current block const epochId = getEpochForBlock(event.block.number); - if (!epochId) { + // FIX: Check for "-1" explicitly, as it is a truthy string + if (epochId == "-1") { log.error("No epoch found for block {}", [event.block.number.toString()]); return; } - // Ensure the Dlp entity exists - const dlp = getOrCreateDlp(event.params.dlpId.toString()); + // FIX: Load DLP instead of creating it to handle non-existent DLP case gracefully + const dlp = Dlp.load(event.params.dlpId.toString()); + if (dlp == null) { + log.error("DLP not found for proof: {}", [event.params.dlpId.toString()]); + return; + } // Create a new DataRegistryProof entity const proof = new DataRegistryProof(event.transaction.hash.toHex()); diff --git a/src/lib/contract/v3/data-registry.ts b/src/lib/contract/v3/data-registry.ts index a9df8d7..b093cb6 100644 --- a/src/lib/contract/v3/data-registry.ts +++ b/src/lib/contract/v3/data-registry.ts @@ -2,6 +2,7 @@ import { BigInt as GraphBigInt, log } from "@graphprotocol/graph-ts"; import { DataRegistryProof, + Dlp, File, FileOwner, } from "../../../../generated/schema"; @@ -10,7 +11,6 @@ import { FileAdded as FileAddedEvent, ProofAdded as FileProofAdded, } from "../../../../generated/DataRegistryImplementationV3/DataRegistryImplementationV3"; -import { getEpochForBlock } from "../../entity/epoch"; import { getOrCreateUserTotals, getUserTotalsId, @@ -21,7 +21,8 @@ import { getTotalsIdDlp, TOTALS_ID_GLOBAL, } from "../../entity/totals"; -import { getOrCreateDlp, getOrCreateUser } from "../shared"; +import { getOrCreateUser } from "../shared"; +import { getEpochForBlock } from "../../entity/epoch"; export function handleFileAddedV3(event: FileAddedEvent): void { log.info("Handling DataRegistry FileAdded with transaction hash: {}", [ @@ -56,13 +57,18 @@ export function handleDataRegistryProofAddedV3(event: FileProofAdded): void { // Get epoch for the current block const epochId = getEpochForBlock(event.block.number); - if (!epochId) { + // Check for "-1" explicitly, as it is a truthy string + if (epochId == "-1") { log.error("No epoch found for block {}", [event.block.number.toString()]); return; } - // Ensure the Dlp entity exists - const dlp = getOrCreateDlp(event.params.dlpId.toString()); + // Load DLP instead of creating it to handle non-existent DLP case gracefully + const dlp = Dlp.load(event.params.dlpId.toString()); + if (dlp == null) { + log.error("DLP not found for proof: {}", [event.params.dlpId.toString()]); + return; + } // Create a new DataRegistryProof entity const proof = new DataRegistryProof(event.transaction.hash.toHex()); diff --git a/src/lib/contract/v5/dlp-registry.ts b/src/lib/contract/v5/dlp-registry.ts index 91feef8..98c2261 100644 --- a/src/lib/contract/v5/dlp-registry.ts +++ b/src/lib/contract/v5/dlp-registry.ts @@ -155,8 +155,15 @@ export function handleDlpTokenUpdatedV5(event: DlpTokenUpdated): void { event.transaction.hash.toHexString(), ]); - // Ensure the Dlp entity exists - const dlp = getOrCreateDlp(event.params.dlpId.toString()); + // Load DLP instead of creating it to handle non-existent DLP case gracefully + const dlp = Dlp.load(event.params.dlpId.toString()); + + if (dlp == null) { + log.error("DLP not found for token update: {}", [ + event.params.dlpId.toString(), + ]); + return; + } dlp.token = event.params.tokenAddress; dlp.save(); From b108c2fadf18ce815c14f1617dac075bb3e782fa Mon Sep 17 00:00:00 2001 From: Volod Date: Thu, 10 Jul 2025 14:02:58 -0400 Subject: [PATCH 15/22] feat: propagate config changes to subgraph.vana.yaml --- config/vana.json | 3 ++- subgraph.vana.yaml | 51 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 1 deletion(-) diff --git a/config/vana.json b/config/vana.json index 65cafca..a391713 100644 --- a/config/vana.json +++ b/config/vana.json @@ -19,7 +19,8 @@ "vanaEpoch": true, "dlpPerformance": true, "queryEngine": true, - "dataRefinerRegistry": true + "dataRefinerRegistry": true, + "dataPermission": true } }, "initParams": { diff --git a/subgraph.vana.yaml b/subgraph.vana.yaml index 76f5152..4b7e427 100644 --- a/subgraph.vana.yaml +++ b/subgraph.vana.yaml @@ -222,3 +222,54 @@ dataSources: - event: EpochDlpPerformancesSaved(indexed uint256,indexed uint256,uint256,uint256,uint256,uint256) handler: handleEpochDlpPerformancesSavedV5 file: ./src/mapping.ts + + - kind: ethereum/contract + name: DataPermissionImplementation + network: vana + source: + address: "0x3acB2023DF2617EFb61422BA0c8C6E97916961e0" + abi: DataPermissionImplementation + startBlock: 3425120 + mapping: + kind: ethereum/events + apiVersion: 0.0.6 + language: wasm/assemblyscript + entities: + - Permission + - User + - TrustedServer + abis: + - name: DataPermissionImplementation + file: ./abis/v5/DataPermissionImplementation.json + eventHandlers: + - event: PermissionAdded(indexed uint256,indexed address,string) + handler: handlePermissionAdded + - event: ServerTrusted(indexed address,indexed address,string) + handler: handleServerTrusted + - event: ServerUntrusted(indexed address,indexed address) + handler: handleServerUntrusted + file: ./src/mapping.ts + + - kind: ethereum/contract + name: DataRegistryImplementationV5 + network: vana + source: + address: "0x8C8788f98385F6ba1adD4234e551ABba0f82Cb7C" + abi: DataRegistryImplementationV5 + startBlock: 3425120 + mapping: + kind: ethereum/events + apiVersion: 0.0.6 + language: wasm/assemblyscript + entities: + - EpochReference + - DataRegistryProof + abis: + - name: DataRegistryImplementationV5 + file: ./abis/v5/DataRegistryImplementation.json + eventHandlers: + - event: FileAdded(indexed uint256,indexed address,string) + handler: handleFileAddedV3 + - event: ProofAdded(indexed uint256,indexed address,uint256,indexed uint256,uint256,string) + handler: handleDataRegistryProofAddedV3 + file: ./src/mapping.ts \ No newline at end of file From bc36c4916bea21014273c621402ca7766c45aa5d Mon Sep 17 00:00:00 2001 From: Volod Date: Thu, 10 Jul 2025 14:07:29 -0400 Subject: [PATCH 16/22] fix: add missing event handlers --- subgraph.moksha.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/subgraph.moksha.yaml b/subgraph.moksha.yaml index 76a8581..d6b2625 100644 --- a/subgraph.moksha.yaml +++ b/subgraph.moksha.yaml @@ -163,6 +163,8 @@ dataSources: handler: handleDlpVerificationUpdatedV5 - event: DlpTokenUpdated(indexed uint256,address) handler: handleDlpTokenUpdatedV5 + - event: DlpSubEligibilityThresholdUpdated(uint256) + handler: handleDlpSubEligibilityThresholdUpdatedV5 - event: DlpRegistrationDepositAmountUpdated(uint256) handler: handleDlpRegistrationDepositAmountUpdatedV5 file: ./src/mapping.ts From dcd845379092ca638585d4a919bfaab175cd4ac4 Mon Sep 17 00:00:00 2001 From: Volod Date: Sat, 12 Jul 2025 11:22:08 -0400 Subject: [PATCH 17/22] feat: support latest smart contract changes --- abis/v5/DataPermissionImplementation.json | 2587 ++++++++++++--------- schema.graphql | 8 +- src/lib/contract/v5/data-permission.ts | 30 +- subgraph.moksha.yaml | 8 +- subgraph.vana-moksha.yaml | 10 +- subgraph.vana.yaml | 8 +- 6 files changed, 1480 insertions(+), 1171 deletions(-) diff --git a/abis/v5/DataPermissionImplementation.json b/abis/v5/DataPermissionImplementation.json index 03bd73a..bf65bda 100644 --- a/abis/v5/DataPermissionImplementation.json +++ b/abis/v5/DataPermissionImplementation.json @@ -1,1159 +1,1434 @@ [ - { - "inputs": [], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "AccessControlBadConfirmation", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "internalType": "bytes32", - "name": "neededRole", - "type": "bytes32" - } - ], - "name": "AccessControlUnauthorizedAccount", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "target", - "type": "address" - } - ], - "name": "AddressEmptyCode", - "type": "error" - }, - { - "inputs": [], - "name": "ECDSAInvalidSignature", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "length", - "type": "uint256" - } - ], - "name": "ECDSAInvalidSignatureLength", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "s", - "type": "bytes32" - } - ], - "name": "ECDSAInvalidSignatureS", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "implementation", - "type": "address" - } - ], - "name": "ERC1967InvalidImplementation", - "type": "error" - }, - { - "inputs": [], - "name": "ERC1967NonPayable", - "type": "error" - }, - { - "inputs": [], - "name": "EmptyGrant", - "type": "error" - }, - { - "inputs": [], - "name": "EmptyUrl", - "type": "error" - }, - { - "inputs": [], - "name": "EnforcedPause", - "type": "error" - }, - { - "inputs": [], - "name": "ExpectedPause", - "type": "error" - }, - { - "inputs": [], - "name": "FailedInnerCall", - "type": "error" - }, - { - "inputs": [], - "name": "GrantAlreadyUsed", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidInitialization", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "expectedNonce", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "providedNonce", - "type": "uint256" - } - ], - "name": "InvalidNonce", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidSignature", - "type": "error" - }, - { - "inputs": [], - "name": "NotInitializing", - "type": "error" - }, - { - "inputs": [], - "name": "ServerAlreadyRegistered", - "type": "error" - }, - { - "inputs": [], - "name": "ServerNotFound", - "type": "error" - }, - { - "inputs": [], - "name": "ServerNotTrusted", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "existingUrl", - "type": "string" - }, - { - "internalType": "string", - "name": "providedUrl", - "type": "string" - } - ], - "name": "ServerUrlMismatch", - "type": "error" - }, - { - "inputs": [], - "name": "UUPSUnauthorizedCallContext", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "slot", - "type": "bytes32" - } - ], - "name": "UUPSUnsupportedProxiableUUID", - "type": "error" - }, - { - "inputs": [], - "name": "ZeroAddress", - "type": "error" - }, - { - "anonymous": false, - "inputs": [], - "name": "EIP712DomainChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint64", - "name": "version", - "type": "uint64" - } - ], - "name": "Initialized", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Paused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "permissionId", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "user", - "type": "address" - }, - { - "indexed": false, - "internalType": "string", - "name": "grant", - "type": "string" - } - ], - "name": "PermissionAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "bytes32", - "name": "previousAdminRole", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "bytes32", - "name": "newAdminRole", - "type": "bytes32" - } - ], - "name": "RoleAdminChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "RoleGranted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "RoleRevoked", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "serverId", - "type": "address" - }, - { - "indexed": false, - "internalType": "string", - "name": "url", - "type": "string" - } - ], - "name": "ServerAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "user", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "serverId", - "type": "address" - }, - { - "indexed": false, - "internalType": "string", - "name": "serverUrl", - "type": "string" - } - ], - "name": "ServerTrusted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "user", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "serverId", - "type": "address" - } - ], - "name": "ServerUntrusted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Unpaused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "implementation", - "type": "address" - } - ], - "name": "Upgraded", - "type": "event" - }, - { - "inputs": [], - "name": "DEFAULT_ADMIN_ROLE", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "MAINTAINER_ROLE", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "UPGRADE_INTERFACE_VERSION", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "uint256", - "name": "nonce", - "type": "uint256" - }, - { - "internalType": "string", - "name": "grant", - "type": "string" - } - ], - "internalType": "struct IDataPermission.PermissionInput", - "name": "permission", - "type": "tuple" - }, - { - "internalType": "bytes", - "name": "signature", - "type": "bytes" - } - ], - "name": "addPermission", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "eip712Domain", - "outputs": [ - { - "internalType": "bytes1", - "name": "fields", - "type": "bytes1" - }, - { - "internalType": "string", - "name": "name", - "type": "string" - }, - { - "internalType": "string", - "name": "version", - "type": "string" - }, - { - "internalType": "uint256", - "name": "chainId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "verifyingContract", - "type": "address" - }, - { - "internalType": "bytes32", - "name": "salt", - "type": "bytes32" - }, - { - "internalType": "uint256[]", - "name": "extensions", - "type": "uint256[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - } - ], - "name": "getRoleAdmin", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "grantRole", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "hasRole", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "trustedForwarderAddress", - "type": "address" - }, - { - "internalType": "address", - "name": "ownerAddress", - "type": "address" - } - ], - "name": "initialize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "forwarder", - "type": "address" - } - ], - "name": "isTrustedForwarder", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes[]", - "name": "data", - "type": "bytes[]" - } - ], - "name": "multicall", - "outputs": [ - { - "internalType": "bytes[]", - "name": "results", - "type": "bytes[]" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "pause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "paused", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "grant", - "type": "string" - } - ], - "name": "permissionIdByGrant", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "permissionId", - "type": "uint256" - } - ], - "name": "permissions", - "outputs": [ - { - "components": [ - { - "internalType": "address", - "name": "user", - "type": "address" - }, - { - "internalType": "uint256", - "name": "nonce", - "type": "uint256" - }, - { - "internalType": "string", - "name": "grant", - "type": "string" - }, - { - "internalType": "bytes", - "name": "signature", - "type": "bytes" - } - ], - "internalType": "struct IDataPermission.Permission", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "permissionsCount", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "proxiableUUID", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "callerConfirmation", - "type": "address" - } - ], - "name": "renounceRole", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "revokeRole", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "serverId", - "type": "address" - } - ], - "name": "servers", - "outputs": [ - { - "components": [ - { - "internalType": "string", - "name": "url", - "type": "string" - } - ], - "internalType": "struct IDataPermission.Server", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "adminRole", - "type": "bytes32" - } - ], - "name": "setRoleAdmin", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes4", - "name": "interfaceId", - "type": "bytes4" - } - ], - "name": "supportsInterface", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "serverId", - "type": "address" - }, - { - "internalType": "string", - "name": "serverUrl", - "type": "string" - } - ], - "name": "trustServer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "uint256", - "name": "nonce", - "type": "uint256" - }, - { - "internalType": "address", - "name": "serverId", - "type": "address" - }, - { - "internalType": "string", - "name": "serverUrl", - "type": "string" - } - ], - "internalType": "struct IDataPermission.TrustServerInput", - "name": "trustServerInput", - "type": "tuple" - }, - { - "internalType": "bytes", - "name": "signature", - "type": "bytes" - } - ], - "name": "trustServerWithSignature", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "trustedForwarder", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "unpause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "serverId", - "type": "address" - } - ], - "name": "untrustServer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "uint256", - "name": "nonce", - "type": "uint256" - }, - { - "internalType": "address", - "name": "serverId", - "type": "address" - } - ], - "internalType": "struct IDataPermission.UntrustServerInput", - "name": "untrustServerInput", - "type": "tuple" - }, - { - "internalType": "bytes", - "name": "signature", - "type": "bytes" - } - ], - "name": "untrustServerWithSignature", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "trustedForwarderAddress", - "type": "address" - } - ], - "name": "updateTrustedForwarder", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "newImplementation", - "type": "address" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "upgradeToAndCall", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "user", - "type": "address" - } - ], - "name": "userNonce", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "user", - "type": "address" - }, - { - "internalType": "uint256", - "name": "permissionIndex", - "type": "uint256" - } - ], - "name": "userPermissionIdsAt", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "user", - "type": "address" - } - ], - "name": "userPermissionIdsLength", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "user", - "type": "address" - } - ], - "name": "userPermissionIdsValues", - "outputs": [ - { - "internalType": "uint256[]", - "name": "", - "type": "uint256[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "user", - "type": "address" - }, - { - "internalType": "uint256", - "name": "serverIndex", - "type": "uint256" - } - ], - "name": "userServerIdsAt", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "user", - "type": "address" - } - ], - "name": "userServerIdsLength", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "user", - "type": "address" - } - ], - "name": "userServerIdsValues", - "outputs": [ - { - "internalType": "address[]", - "name": "", - "type": "address[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "AccessControlBadConfirmation", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "neededRole", + "type": "bytes32" + } + ], + "name": "AccessControlUnauthorizedAccount", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + } + ], + "name": "AddressEmptyCode", + "type": "error" + }, + { + "inputs": [], + "name": "ECDSAInvalidSignature", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "length", + "type": "uint256" + } + ], + "name": "ECDSAInvalidSignatureLength", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "ECDSAInvalidSignatureS", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "ERC1967InvalidImplementation", + "type": "error" + }, + { + "inputs": [], + "name": "ERC1967NonPayable", + "type": "error" + }, + { + "inputs": [], + "name": "EmptyGrant", + "type": "error" + }, + { + "inputs": [], + "name": "EmptyUrl", + "type": "error" + }, + { + "inputs": [], + "name": "EnforcedPause", + "type": "error" + }, + { + "inputs": [], + "name": "ExpectedPause", + "type": "error" + }, + { + "inputs": [], + "name": "FailedInnerCall", + "type": "error" + }, + { + "inputs": [], + "name": "GrantAlreadyUsed", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "permissionId", + "type": "uint256" + } + ], + "name": "InactivePermission", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidInitialization", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "expectedNonce", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "providedNonce", + "type": "uint256" + } + ], + "name": "InvalidNonce", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidSignature", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "fileOwner", + "type": "address" + }, + { + "internalType": "address", + "name": "requestor", + "type": "address" + } + ], + "name": "NotFileOwner", + "type": "error" + }, + { + "inputs": [], + "name": "NotInitializing", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "permissionOwner", + "type": "address" + }, + { + "internalType": "address", + "name": "requestor", + "type": "address" + } + ], + "name": "NotPermissionGrantor", + "type": "error" + }, + { + "inputs": [], + "name": "ServerAlreadyRegistered", + "type": "error" + }, + { + "inputs": [], + "name": "ServerNotFound", + "type": "error" + }, + { + "inputs": [], + "name": "ServerNotTrusted", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "existingUrl", + "type": "string" + }, + { + "internalType": "string", + "name": "providedUrl", + "type": "string" + } + ], + "name": "ServerUrlMismatch", + "type": "error" + }, + { + "inputs": [], + "name": "UUPSUnauthorizedCallContext", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "slot", + "type": "bytes32" + } + ], + "name": "UUPSUnsupportedProxiableUUID", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddress", + "type": "error" + }, + { + "anonymous": false, + "inputs": [], + "name": "EIP712DomainChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint64", "name": "version", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - } + "type": "uint64" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "permissionId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": false, + "internalType": "string", + "name": "grant", + "type": "string" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "fileIds", + "type": "uint256[]" + } + ], + "name": "PermissionAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "permissionId", + "type": "uint256" + } + ], + "name": "PermissionRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "previousAdminRole", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "newAdminRole", + "type": "bytes32" + } + ], + "name": "RoleAdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "serverId", + "type": "address" + }, + { + "indexed": false, + "internalType": "string", + "name": "url", + "type": "string" + } + ], + "name": "ServerAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "serverId", + "type": "address" + }, + { + "indexed": false, + "internalType": "string", + "name": "serverUrl", + "type": "string" + } + ], + "name": "ServerTrusted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "serverId", + "type": "address" + } + ], + "name": "ServerUntrusted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "inputs": [], + "name": "DEFAULT_ADMIN_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAINTAINER_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "UPGRADE_INTERFACE_VERSION", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "string", + "name": "grant", + "type": "string" + }, + { + "internalType": "uint256[]", + "name": "fileIds", + "type": "uint256[]" + } + ], + "internalType": "struct IDataPermissions.PermissionInput", + "name": "permission", + "type": "tuple" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "name": "addPermission", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "dataRegistry", + "outputs": [ + { + "internalType": "contract IDataRegistry", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "eip712Domain", + "outputs": [ + { + "internalType": "bytes1", + "name": "fields", + "type": "bytes1" + }, + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "version", + "type": "string" + }, + { + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "verifyingContract", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "salt", + "type": "bytes32" + }, + { + "internalType": "uint256[]", + "name": "extensions", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "fileId", + "type": "uint256" + } + ], + "name": "filePermissionIds", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleAdmin", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRole", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "trustedForwarderAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "ownerAddress", + "type": "address" + }, + { + "internalType": "contract IDataRegistry", + "name": "dataRegistryAddress", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "permissionId", + "type": "uint256" + } + ], + "name": "isActivePermission", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "forwarder", + "type": "address" + } + ], + "name": "isTrustedForwarder", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes[]", + "name": "data", + "type": "bytes[]" + } + ], + "name": "multicall", + "outputs": [ + { + "internalType": "bytes[]", + "name": "results", + "type": "bytes[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "paused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "permissionId", + "type": "uint256" + } + ], + "name": "permissionFileIds", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "grant", + "type": "string" + } + ], + "name": "permissionIdByGrant", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "permissionId", + "type": "uint256" + } + ], + "name": "permissions", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "address", + "name": "grantor", + "type": "address" + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "string", + "name": "grant", + "type": "string" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + }, + { + "internalType": "bool", + "name": "isActive", + "type": "bool" + }, + { + "internalType": "uint256[]", + "name": "fileIds", + "type": "uint256[]" + } + ], + "internalType": "struct IDataPermissions.PermissionInfo", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "permissionsCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proxiableUUID", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "callerConfirmation", + "type": "address" + } + ], + "name": "renounceRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "permissionId", + "type": "uint256" + } + ], + "name": "revokePermission", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "permissionId", + "type": "uint256" + } + ], + "internalType": "struct IDataPermissions.RevokePermissionInput", + "name": "revokePermissionInput", + "type": "tuple" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "name": "revokePermissionWithSignature", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serverId", + "type": "address" + } + ], + "name": "servers", + "outputs": [ + { + "components": [ + { + "internalType": "string", + "name": "url", + "type": "string" + } + ], + "internalType": "struct IDataPermissions.Server", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "adminRole", + "type": "bytes32" + } + ], + "name": "setRoleAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serverId", + "type": "address" + }, + { + "internalType": "string", + "name": "serverUrl", + "type": "string" + } + ], + "name": "trustServer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "address", + "name": "serverId", + "type": "address" + }, + { + "internalType": "string", + "name": "serverUrl", + "type": "string" + } + ], + "internalType": "struct IDataPermissions.TrustServerInput", + "name": "trustServerInput", + "type": "tuple" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "name": "trustServerWithSignature", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "trustedForwarder", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "unpause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serverId", + "type": "address" + } + ], + "name": "untrustServer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "address", + "name": "serverId", + "type": "address" + } + ], + "internalType": "struct IDataPermissions.UntrustServerInput", + "name": "untrustServerInput", + "type": "tuple" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "name": "untrustServerWithSignature", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IDataRegistry", + "name": "newDataRegistry", + "type": "address" + } + ], + "name": "updateDataRegistry", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "trustedForwarderAddress", + "type": "address" + } + ], + "name": "updateTrustedForwarder", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "userNonce", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "internalType": "uint256", + "name": "permissionIndex", + "type": "uint256" + } + ], + "name": "userPermissionIdsAt", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "userPermissionIdsLength", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "userPermissionIdsValues", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "internalType": "uint256", + "name": "permissionIndex", + "type": "uint256" + } + ], + "name": "userRevokedPermissionIdsAt", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "userRevokedPermissionIdsLength", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "userRevokedPermissionIdsValues", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "internalType": "uint256", + "name": "serverIndex", + "type": "uint256" + } + ], + "name": "userServerIdsAt", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "userServerIdsLength", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "userServerIdsValues", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + } ] \ No newline at end of file diff --git a/schema.graphql b/schema.graphql index 3b12a31..3b5dc0b 100644 --- a/schema.graphql +++ b/schema.graphql @@ -4,7 +4,7 @@ type User @entity(immutable: false) { "All files owned by this user" files: [File!]! @derivedFrom(field: "owner") "All permissions granted by this user" - permissions: [Permission!]! @derivedFrom(field: "user") + permissions: [Permission!]! @derivedFrom(field: "grantor") "All servers trusted by this user" trustedServers: [TrustedServer!]! @derivedFrom(field: "user") } @@ -158,13 +158,17 @@ type Permission @entity(immutable: false) { "The unique ID of the permission, equivalent to the on-chain permissionId." id: ID! "The user who granted the permission." - user: User! + grantor: User! "The content identifier (e.g., IPFS URL) for the grant details." grant: String! "The nonce used for this permission grant." nonce: BigInt! "The signature provided by the user." signature: Bytes! + "Whether the permission is currently active or has been revoked." + isActive: Boolean! + "File IDs associated with this permission." + fileIds: [BigInt!]! "The block number when the permission was granted." addedAtBlock: BigInt! "The timestamp when the permission was granted." diff --git a/src/lib/contract/v5/data-permission.ts b/src/lib/contract/v5/data-permission.ts index 440c429..70af0d3 100644 --- a/src/lib/contract/v5/data-permission.ts +++ b/src/lib/contract/v5/data-permission.ts @@ -6,6 +6,7 @@ import { } from "@graphprotocol/graph-ts"; import { PermissionAdded, + PermissionRevoked, ServerTrusted, ServerUntrusted, DataPermissionImplementation, @@ -18,22 +19,26 @@ export function handlePermissionAdded(event: PermissionAdded): void { event.transaction.hash.toHexString(), ]); - const user = getOrCreateUser(event.params.user.toHex()); + const grantor = getOrCreateUser(event.params.user.toHex()); const permissionId = event.params.permissionId; const permission = new Permission(permissionId.toString()); - permission.user = user.id; + permission.grantor = grantor.id; // Renamed from 'user' to 'grantor' permission.grant = event.params.grant; permission.addedAtBlock = event.block.number; permission.addedAtTimestamp = event.block.timestamp; permission.transactionHash = event.transaction.hash; + // Set new fields + permission.isActive = true; // New permissions are active by default + permission.fileIds = event.params.fileIds; // Store the new fileIds array + // Since nonce and signature are not in the event, we must call the contract. const contract = DataPermissionImplementation.bind(event.address); const permissionData = contract.try_permissions(permissionId); if (!permissionData.reverted) { - // FIX: Access properties directly instead of using getters. + // The returned struct has a 'grantor' field, not 'user' permission.nonce = permissionData.value.nonce; permission.signature = permissionData.value.signature; } else { @@ -42,13 +47,30 @@ export function handlePermissionAdded(event: PermissionAdded): void { [permissionId.toString()], ); permission.nonce = GraphBigInt.zero(); - // FIX: Use an empty Bytes array for an empty signature. permission.signature = new Bytes(0); } permission.save(); } +export function handlePermissionRevoked(event: PermissionRevoked): void { + log.info("Handling PermissionRevoked for permissionId: {}", [ + event.params.permissionId.toString(), + ]); + + const permissionId = event.params.permissionId.toString(); + const permission = Permission.load(permissionId); + + if (permission) { + permission.isActive = false; + permission.save(); + } else { + log.warning("Received revoke event for a permission not found in subgraph: {}", [ + permissionId, + ]); + } +} + export function handleServerTrusted(event: ServerTrusted): void { log.info("Handling ServerTrusted for user {} and server {}", [ event.params.user.toHex(), diff --git a/subgraph.moksha.yaml b/subgraph.moksha.yaml index d6b2625..c6c57ef 100644 --- a/subgraph.moksha.yaml +++ b/subgraph.moksha.yaml @@ -227,9 +227,9 @@ dataSources: name: DataPermissionImplementation network: moksha source: - address: "0x3acB2023DF2617EFb61422BA0c8C6E97916961e0" + address: "0x31fb1D48f6B2265A4cAD516BC39E96a18fb7c8de" abi: DataPermissionImplementation - startBlock: 3425120 + startBlock: 3517249 mapping: kind: ethereum/events apiVersion: 0.0.6 @@ -242,8 +242,10 @@ dataSources: - name: DataPermissionImplementation file: ./abis/v5/DataPermissionImplementation.json eventHandlers: - - event: PermissionAdded(indexed uint256,indexed address,string) + - event: PermissionAdded(indexed uint256,indexed address,string,uint256[]) handler: handlePermissionAdded + - event: PermissionRevoked(indexed uint256) + handler: handlePermissionRevoked - event: ServerTrusted(indexed address,indexed address,string) handler: handleServerTrusted - event: ServerUntrusted(indexed address,indexed address) diff --git a/subgraph.vana-moksha.yaml b/subgraph.vana-moksha.yaml index c9353dd..ff7305e 100644 --- a/subgraph.vana-moksha.yaml +++ b/subgraph.vana-moksha.yaml @@ -163,6 +163,8 @@ dataSources: handler: handleDlpVerificationUpdatedV5 - event: DlpTokenUpdated(indexed uint256,address) handler: handleDlpTokenUpdatedV5 + - event: DlpSubEligibilityThresholdUpdated(uint256) + handler: handleDlpSubEligibilityThresholdUpdatedV5 - event: DlpRegistrationDepositAmountUpdated(uint256) handler: handleDlpRegistrationDepositAmountUpdatedV5 file: ./src/mapping.ts @@ -225,9 +227,9 @@ dataSources: name: DataPermissionImplementation network: vana-moksha source: - address: "0x3acB2023DF2617EFb61422BA0c8C6E97916961e0" + address: "0x31fb1D48f6B2265A4cAD516BC39E96a18fb7c8de" abi: DataPermissionImplementation - startBlock: 3425120 + startBlock: 3517249 mapping: kind: ethereum/events apiVersion: 0.0.6 @@ -240,8 +242,10 @@ dataSources: - name: DataPermissionImplementation file: ./abis/v5/DataPermissionImplementation.json eventHandlers: - - event: PermissionAdded(indexed uint256,indexed address,string) + - event: PermissionAdded(indexed uint256,indexed address,string,uint256[]) handler: handlePermissionAdded + - event: PermissionRevoked(indexed uint256) + handler: handlePermissionRevoked - event: ServerTrusted(indexed address,indexed address,string) handler: handleServerTrusted - event: ServerUntrusted(indexed address,indexed address) diff --git a/subgraph.vana.yaml b/subgraph.vana.yaml index 4b7e427..5b69dd6 100644 --- a/subgraph.vana.yaml +++ b/subgraph.vana.yaml @@ -227,9 +227,9 @@ dataSources: name: DataPermissionImplementation network: vana source: - address: "0x3acB2023DF2617EFb61422BA0c8C6E97916961e0" + address: "0x31fb1D48f6B2265A4cAD516BC39E96a18fb7c8de" abi: DataPermissionImplementation - startBlock: 3425120 + startBlock: 3965727 mapping: kind: ethereum/events apiVersion: 0.0.6 @@ -242,8 +242,10 @@ dataSources: - name: DataPermissionImplementation file: ./abis/v5/DataPermissionImplementation.json eventHandlers: - - event: PermissionAdded(indexed uint256,indexed address,string) + - event: PermissionAdded(indexed uint256,indexed address,string,uint256[]) handler: handlePermissionAdded + - event: PermissionRevoked(indexed uint256) + handler: handlePermissionRevoked - event: ServerTrusted(indexed address,indexed address,string) handler: handleServerTrusted - event: ServerUntrusted(indexed address,indexed address) From 5c6c41f8bdf85b9aafeba3b03bc9820f22d050c1 Mon Sep 17 00:00:00 2001 From: Eduard Dumea Date: Fri, 18 Jul 2025 23:51:43 +0300 Subject: [PATCH 18/22] master refactor --- .gitignore | 8 +- .subgraph-env | 2 + abis/uniswap/ERC20.json | 222 +++ abis/uniswap/ERC20NameBytes.json | 17 + abis/uniswap/ERC20SymbolBytes.json | 17 + abis/uniswap/NonfungiblePositionManager.json | 1193 +++++++++++++++++ abis/uniswap/factory.json | 198 +++ abis/uniswap/pool.json | 988 ++++++++++++++ abis/v1/empty.json | 1 + abis/v5/DLPRegistryImplementation.json | 752 +++++++++-- config/moksha.json | 6 +- config/uniswap/moksha/chain.ts | 44 + config/uniswap/vana/chain.ts | 49 + config/vana.json | 36 + package.json | 8 +- schema.graphql | 523 +++++++- src/lib/contract/shared.ts | 31 +- src/lib/contract/shared/constants.ts | 18 + src/lib/contract/shared/entity-factory.ts | 58 + src/lib/contract/shared/entity-utils.ts | 55 + src/lib/contract/shared/event-utils.ts | 78 ++ src/lib/contract/shared/file-handlers.ts | 58 + src/lib/contract/shared/index.ts | 15 + src/lib/contract/shared/proof-handlers.ts | 60 + src/lib/contract/shared/totals-updater.ts | 107 ++ src/lib/contract/v1/data-registry.ts | 123 +- src/lib/contract/v2/data-registry.ts | 163 +-- src/lib/contract/v3/data-registry.ts | 200 ++- src/lib/contract/v4/query-engine.ts | 23 + src/lib/contract/v5/data-permission.ts | 31 +- src/lib/contract/v5/data-refiner-registry.ts | 20 - src/lib/contract/v5/dlp-registry.ts | 61 +- src/lib/contract/v5/query-engine.ts | 32 - src/lib/entity/bootstrap/bootstrap.ts | 14 + src/lib/entity/dlpEpochUser/constants.ts | 7 + src/lib/entity/dlpEpochUser/dlp-epoch-user.ts | 17 + src/lib/entity/dlpEpochUser/index.ts | 2 + src/lib/entity/totals/constants.ts | 9 +- src/lib/entity/totals/totals.ts | 14 +- src/mapping.ts.template | 24 +- src/uniswap/common/backfill.ts | 125 ++ src/uniswap/common/constants.ts | 14 + src/uniswap/common/entityGetters.ts | 54 + src/uniswap/common/position.ts | 18 + src/uniswap/common/pricing.ts | 125 ++ src/uniswap/common/staticTokenDefinition.ts | 20 + src/uniswap/common/tick.ts | 58 + src/uniswap/common/token.ts | 89 ++ src/uniswap/common/utils.ts | 124 ++ src/uniswap/v3/mappings/burn.ts | 106 ++ src/uniswap/v3/mappings/collect.ts | 105 ++ src/uniswap/v3/mappings/core.ts | 7 + src/uniswap/v3/mappings/factory.ts | 152 +++ src/uniswap/v3/mappings/initialize.ts | 34 + src/uniswap/v3/mappings/intervalUpdates.ts | 205 +++ src/uniswap/v3/mappings/mint.ts | 138 ++ src/uniswap/v3/mappings/swap.ts | 208 +++ src/uniswap/v3/mappings/tick.ts | 28 + src/uniswap/v3/mappings/utils.ts | 16 + src/uniswap/v3/schema.graphql | 498 +++++++ subgraph.moksha.yaml | 96 +- subgraph.vana-moksha.yaml | 92 +- subgraph.vana.yaml | 100 +- tests/unit/contract/utils/file-owner.ts | 22 +- .../v1/data-registry-refactored.test.ts | 137 ++ tests/unit/contract/v1/data-registry.test.ts | 16 +- .../contract/v1/utils/data-registry-events.ts | 22 +- tests/unit/contract/v2/data-registry.test.ts | 14 +- tests/unit/contract/v3/data-registry.test.ts | 12 +- .../contract/v5/utils/dlp-registry-events.ts | 18 - .../integration/refactored-handlers.test.ts | 190 +++ .../lib/contract/shared/constants.test.ts | 40 + .../lib/contract/shared/event-utils.test.ts | 160 +++ .../lib/contract/shared/file-handlers.test.ts | 95 ++ .../contract/shared/proof-handlers.test.ts | 109 ++ .../contract/shared/totals-updater.test.ts | 175 +++ 76 files changed, 8051 insertions(+), 655 deletions(-) create mode 100644 .subgraph-env create mode 100644 abis/uniswap/ERC20.json create mode 100644 abis/uniswap/ERC20NameBytes.json create mode 100644 abis/uniswap/ERC20SymbolBytes.json create mode 100644 abis/uniswap/NonfungiblePositionManager.json create mode 100644 abis/uniswap/factory.json create mode 100644 abis/uniswap/pool.json create mode 100644 abis/v1/empty.json create mode 100644 config/uniswap/moksha/chain.ts create mode 100644 config/uniswap/vana/chain.ts create mode 100644 src/lib/contract/shared/constants.ts create mode 100644 src/lib/contract/shared/entity-factory.ts create mode 100644 src/lib/contract/shared/entity-utils.ts create mode 100644 src/lib/contract/shared/event-utils.ts create mode 100644 src/lib/contract/shared/file-handlers.ts create mode 100644 src/lib/contract/shared/index.ts create mode 100644 src/lib/contract/shared/proof-handlers.ts create mode 100644 src/lib/contract/shared/totals-updater.ts delete mode 100644 src/lib/contract/v5/data-refiner-registry.ts delete mode 100644 src/lib/contract/v5/query-engine.ts create mode 100644 src/lib/entity/bootstrap/bootstrap.ts create mode 100644 src/lib/entity/dlpEpochUser/constants.ts create mode 100644 src/lib/entity/dlpEpochUser/dlp-epoch-user.ts create mode 100644 src/lib/entity/dlpEpochUser/index.ts create mode 100644 src/uniswap/common/backfill.ts create mode 100644 src/uniswap/common/constants.ts create mode 100644 src/uniswap/common/entityGetters.ts create mode 100644 src/uniswap/common/position.ts create mode 100644 src/uniswap/common/pricing.ts create mode 100644 src/uniswap/common/staticTokenDefinition.ts create mode 100644 src/uniswap/common/tick.ts create mode 100644 src/uniswap/common/token.ts create mode 100644 src/uniswap/common/utils.ts create mode 100644 src/uniswap/v3/mappings/burn.ts create mode 100644 src/uniswap/v3/mappings/collect.ts create mode 100644 src/uniswap/v3/mappings/core.ts create mode 100644 src/uniswap/v3/mappings/factory.ts create mode 100644 src/uniswap/v3/mappings/initialize.ts create mode 100644 src/uniswap/v3/mappings/intervalUpdates.ts create mode 100644 src/uniswap/v3/mappings/mint.ts create mode 100644 src/uniswap/v3/mappings/swap.ts create mode 100644 src/uniswap/v3/mappings/tick.ts create mode 100644 src/uniswap/v3/mappings/utils.ts create mode 100644 src/uniswap/v3/schema.graphql create mode 100644 tests/unit/contract/v1/data-registry-refactored.test.ts create mode 100644 tests/unit/integration/refactored-handlers.test.ts create mode 100644 tests/unit/lib/contract/shared/constants.test.ts create mode 100644 tests/unit/lib/contract/shared/event-utils.test.ts create mode 100644 tests/unit/lib/contract/shared/file-handlers.test.ts create mode 100644 tests/unit/lib/contract/shared/proof-handlers.test.ts create mode 100644 tests/unit/lib/contract/shared/totals-updater.test.ts diff --git a/.gitignore b/.gitignore index e08b2aa..c4e982d 100644 --- a/.gitignore +++ b/.gitignore @@ -62,7 +62,7 @@ typings/ # matchstick output tests/unit/.docker -tests/unit/.bin +tests/unit/.bin tests/unit/.latest.json subgraph.yaml @@ -71,4 +71,8 @@ subgraph.yaml build generated -src/mapping.ts \ No newline at end of file +src/mapping.ts + +src/uniswap/common/chain.ts + +CLAUDE.md \ No newline at end of file diff --git a/.subgraph-env b/.subgraph-env new file mode 100644 index 0000000..e9a5a34 --- /dev/null +++ b/.subgraph-env @@ -0,0 +1,2 @@ +V3_TOKEN_SUBGRAPH_NAME="uniswap-v3-vana-tokens" +V3_SUBGRAPH_NAME="uniswap-v3-vana" \ No newline at end of file diff --git a/abis/uniswap/ERC20.json b/abis/uniswap/ERC20.json new file mode 100644 index 0000000..c81c27b --- /dev/null +++ b/abis/uniswap/ERC20.json @@ -0,0 +1,222 @@ +[ + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_spender", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_from", + "type": "address" + }, + { + "name": "_to", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "_owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "name": "balance", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_to", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "_owner", + "type": "address" + }, + { + "name": "_spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "payable": true, + "stateMutability": "payable", + "type": "fallback" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "from", + "type": "address" + }, + { + "indexed": true, + "name": "to", + "type": "address" + }, + { + "indexed": false, + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + } +] diff --git a/abis/uniswap/ERC20NameBytes.json b/abis/uniswap/ERC20NameBytes.json new file mode 100644 index 0000000..2d3c877 --- /dev/null +++ b/abis/uniswap/ERC20NameBytes.json @@ -0,0 +1,17 @@ +[ + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } +] diff --git a/abis/uniswap/ERC20SymbolBytes.json b/abis/uniswap/ERC20SymbolBytes.json new file mode 100644 index 0000000..a76d616 --- /dev/null +++ b/abis/uniswap/ERC20SymbolBytes.json @@ -0,0 +1,17 @@ +[ + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } +] diff --git a/abis/uniswap/NonfungiblePositionManager.json b/abis/uniswap/NonfungiblePositionManager.json new file mode 100644 index 0000000..29cef05 --- /dev/null +++ b/abis/uniswap/NonfungiblePositionManager.json @@ -0,0 +1,1193 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "_factory", + "type": "address" + }, + { + "internalType": "address", + "name": "_WETH9", + "type": "address" + }, + { + "internalType": "address", + "name": "_tokenDescriptor_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "approved", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "ApprovalForAll", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount0", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount1", + "type": "uint256" + } + ], + "name": "Collect", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint128", + "name": "liquidity", + "type": "uint128" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount0", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount1", + "type": "uint256" + } + ], + "name": "DecreaseLiquidity", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint128", + "name": "liquidity", + "type": "uint128" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount0", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount1", + "type": "uint256" + } + ], + "name": "IncreaseLiquidity", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [], + "name": "DOMAIN_SEPARATOR", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "PERMIT_TYPEHASH", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "WETH9", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "baseURI", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "burn", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint128", + "name": "amount0Max", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "amount1Max", + "type": "uint128" + } + ], + "name": "collect", + "outputs": [ + { + "internalType": "uint256", + "name": "amount0", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount1", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenA", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenB", + "type": "address" + }, + { + "internalType": "uint24", + "name": "fee", + "type": "uint24" + }, + { + "internalType": "uint160", + "name": "sqrtPriceX96", + "type": "uint160" + } + ], + "name": "createAndInitializePoolIfNecessary", + "outputs": [ + { + "internalType": "address", + "name": "pool", + "type": "address" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "uint128", + "name": "liquidity", + "type": "uint128" + }, + { + "internalType": "uint256", + "name": "amount0Min", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount1Min", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "decreaseLiquidity", + "outputs": [ + { + "internalType": "uint256", + "name": "amount0", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount1", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "factory", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "getApproved", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount0Desired", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount1Desired", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount0Min", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount1Min", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "increaseLiquidity", + "outputs": [ + { + "internalType": "uint128", + "name": "liquidity", + "type": "uint128" + }, + { + "internalType": "uint256", + "name": "amount0", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount1", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "isApprovedForAll", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "token0", + "type": "address" + }, + { + "internalType": "address", + "name": "token1", + "type": "address" + }, + { + "internalType": "uint24", + "name": "fee", + "type": "uint24" + }, + { + "internalType": "int24", + "name": "tickLower", + "type": "int24" + }, + { + "internalType": "int24", + "name": "tickUpper", + "type": "int24" + }, + { + "internalType": "uint256", + "name": "amount0Desired", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount1Desired", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount0Min", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount1Min", + "type": "uint256" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "internalType": "struct INonfungiblePositionManager.MintParams", + "name": "params", + "type": "tuple" + } + ], + "name": "mint", + "outputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "uint128", + "name": "liquidity", + "type": "uint128" + }, + { + "internalType": "uint256", + "name": "amount0", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount1", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes[]", + "name": "data", + "type": "bytes[]" + } + ], + "name": "multicall", + "outputs": [ + { + "internalType": "bytes[]", + "name": "results", + "type": "bytes[]" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "ownerOf", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "permit", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "positions", + "outputs": [ + { + "internalType": "uint96", + "name": "nonce", + "type": "uint96" + }, + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "address", + "name": "token0", + "type": "address" + }, + { + "internalType": "address", + "name": "token1", + "type": "address" + }, + { + "internalType": "uint24", + "name": "fee", + "type": "uint24" + }, + { + "internalType": "int24", + "name": "tickLower", + "type": "int24" + }, + { + "internalType": "int24", + "name": "tickUpper", + "type": "int24" + }, + { + "internalType": "uint128", + "name": "liquidity", + "type": "uint128" + }, + { + "internalType": "uint256", + "name": "feeGrowthInside0LastX128", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "feeGrowthInside1LastX128", + "type": "uint256" + }, + { + "internalType": "uint128", + "name": "tokensOwed0", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "tokensOwed1", + "type": "uint128" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "selfPermit", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "expiry", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "selfPermitAllowed", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "expiry", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "selfPermitAllowedIfNecessary", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "selfPermitIfNecessary", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "setApprovalForAll", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountMinimum", + "type": "uint256" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + } + ], + "name": "sweepToken", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "name": "tokenByIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "name": "tokenOfOwnerByIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "tokenURI", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount0Owed", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount1Owed", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "uniswapV3MintCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountMinimum", + "type": "uint256" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + } + ], + "name": "unwrapWETH9", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } +] \ No newline at end of file diff --git a/abis/uniswap/factory.json b/abis/uniswap/factory.json new file mode 100644 index 0000000..2503212 --- /dev/null +++ b/abis/uniswap/factory.json @@ -0,0 +1,198 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint24", + "name": "fee", + "type": "uint24" + }, + { + "indexed": true, + "internalType": "int24", + "name": "tickSpacing", + "type": "int24" + } + ], + "name": "FeeAmountEnabled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnerChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "token0", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "token1", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint24", + "name": "fee", + "type": "uint24" + }, + { + "indexed": false, + "internalType": "int24", + "name": "tickSpacing", + "type": "int24" + }, + { + "indexed": false, + "internalType": "address", + "name": "pool", + "type": "address" + } + ], + "name": "PoolCreated", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenA", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenB", + "type": "address" + }, + { + "internalType": "uint24", + "name": "fee", + "type": "uint24" + } + ], + "name": "createPool", + "outputs": [ + { + "internalType": "address", + "name": "pool", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint24", + "name": "fee", + "type": "uint24" + }, + { + "internalType": "int24", + "name": "tickSpacing", + "type": "int24" + } + ], + "name": "enableFeeAmount", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint24", + "name": "fee", + "type": "uint24" + } + ], + "name": "feeAmountTickSpacing", + "outputs": [ + { + "internalType": "int24", + "name": "", + "type": "int24" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenA", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenB", + "type": "address" + }, + { + "internalType": "uint24", + "name": "fee", + "type": "uint24" + } + ], + "name": "getPool", + "outputs": [ + { + "internalType": "address", + "name": "pool", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_owner", + "type": "address" + } + ], + "name": "setOwner", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] \ No newline at end of file diff --git a/abis/uniswap/pool.json b/abis/uniswap/pool.json new file mode 100644 index 0000000..c87d64d --- /dev/null +++ b/abis/uniswap/pool.json @@ -0,0 +1,988 @@ +[ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "int24", + "name": "tickLower", + "type": "int24" + }, + { + "indexed": true, + "internalType": "int24", + "name": "tickUpper", + "type": "int24" + }, + { + "indexed": false, + "internalType": "uint128", + "name": "amount", + "type": "uint128" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount0", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount1", + "type": "uint256" + } + ], + "name": "Burn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "indexed": true, + "internalType": "int24", + "name": "tickLower", + "type": "int24" + }, + { + "indexed": true, + "internalType": "int24", + "name": "tickUpper", + "type": "int24" + }, + { + "indexed": false, + "internalType": "uint128", + "name": "amount0", + "type": "uint128" + }, + { + "indexed": false, + "internalType": "uint128", + "name": "amount1", + "type": "uint128" + } + ], + "name": "Collect", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint128", + "name": "amount0", + "type": "uint128" + }, + { + "indexed": false, + "internalType": "uint128", + "name": "amount1", + "type": "uint128" + } + ], + "name": "CollectProtocol", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount0", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount1", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "paid0", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "paid1", + "type": "uint256" + } + ], + "name": "Flash", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint16", + "name": "observationCardinalityNextOld", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "uint16", + "name": "observationCardinalityNextNew", + "type": "uint16" + } + ], + "name": "IncreaseObservationCardinalityNext", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint160", + "name": "sqrtPriceX96", + "type": "uint160" + }, + { + "indexed": false, + "internalType": "int24", + "name": "tick", + "type": "int24" + } + ], + "name": "Initialize", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "int24", + "name": "tickLower", + "type": "int24" + }, + { + "indexed": true, + "internalType": "int24", + "name": "tickUpper", + "type": "int24" + }, + { + "indexed": false, + "internalType": "uint128", + "name": "amount", + "type": "uint128" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount0", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount1", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "feeProtocol0Old", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "feeProtocol1Old", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "feeProtocol0New", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "feeProtocol1New", + "type": "uint8" + } + ], + "name": "SetFeeProtocol", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "indexed": false, + "internalType": "int256", + "name": "amount0", + "type": "int256" + }, + { + "indexed": false, + "internalType": "int256", + "name": "amount1", + "type": "int256" + }, + { + "indexed": false, + "internalType": "uint160", + "name": "sqrtPriceX96", + "type": "uint160" + }, + { + "indexed": false, + "internalType": "uint128", + "name": "liquidity", + "type": "uint128" + }, + { + "indexed": false, + "internalType": "int24", + "name": "tick", + "type": "int24" + } + ], + "name": "Swap", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "int24", + "name": "tickLower", + "type": "int24" + }, + { + "internalType": "int24", + "name": "tickUpper", + "type": "int24" + }, + { + "internalType": "uint128", + "name": "amount", + "type": "uint128" + } + ], + "name": "burn", + "outputs": [ + { + "internalType": "uint256", + "name": "amount0", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount1", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "int24", + "name": "tickLower", + "type": "int24" + }, + { + "internalType": "int24", + "name": "tickUpper", + "type": "int24" + }, + { + "internalType": "uint128", + "name": "amount0Requested", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "amount1Requested", + "type": "uint128" + } + ], + "name": "collect", + "outputs": [ + { + "internalType": "uint128", + "name": "amount0", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "amount1", + "type": "uint128" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint128", + "name": "amount0Requested", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "amount1Requested", + "type": "uint128" + } + ], + "name": "collectProtocol", + "outputs": [ + { + "internalType": "uint128", + "name": "amount0", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "amount1", + "type": "uint128" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "factory", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "fee", + "outputs": [ + { + "internalType": "uint24", + "name": "", + "type": "uint24" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "feeGrowthGlobal0X128", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "feeGrowthGlobal1X128", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount0", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount1", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "flash", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "observationCardinalityNext", + "type": "uint16" + } + ], + "name": "increaseObservationCardinalityNext", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint160", + "name": "sqrtPriceX96", + "type": "uint160" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "liquidity", + "outputs": [ + { + "internalType": "uint128", + "name": "", + "type": "uint128" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "maxLiquidityPerTick", + "outputs": [ + { + "internalType": "uint128", + "name": "", + "type": "uint128" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "int24", + "name": "tickLower", + "type": "int24" + }, + { + "internalType": "int24", + "name": "tickUpper", + "type": "int24" + }, + { + "internalType": "uint128", + "name": "amount", + "type": "uint128" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "mint", + "outputs": [ + { + "internalType": "uint256", + "name": "amount0", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount1", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "name": "observations", + "outputs": [ + { + "internalType": "uint32", + "name": "blockTimestamp", + "type": "uint32" + }, + { + "internalType": "int56", + "name": "tickCumulative", + "type": "int56" + }, + { + "internalType": "uint160", + "name": "secondsPerLiquidityCumulativeX128", + "type": "uint160" + }, + { + "internalType": "bool", + "name": "initialized", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32[]", + "name": "secondsAgos", + "type": "uint32[]" + } + ], + "name": "observe", + "outputs": [ + { + "internalType": "int56[]", + "name": "tickCumulatives", + "type": "int56[]" + }, + { + "internalType": "uint160[]", + "name": "secondsPerLiquidityCumulativeX128s", + "type": "uint160[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "key", + "type": "bytes32" + } + ], + "name": "positions", + "outputs": [ + { + "internalType": "uint128", + "name": "_liquidity", + "type": "uint128" + }, + { + "internalType": "uint256", + "name": "feeGrowthInside0LastX128", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "feeGrowthInside1LastX128", + "type": "uint256" + }, + { + "internalType": "uint128", + "name": "tokensOwed0", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "tokensOwed1", + "type": "uint128" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "protocolFees", + "outputs": [ + { + "internalType": "uint128", + "name": "token0", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "token1", + "type": "uint128" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "feeProtocol0", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "feeProtocol1", + "type": "uint8" + } + ], + "name": "setFeeProtocol", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "slot0", + "outputs": [ + { + "internalType": "uint160", + "name": "sqrtPriceX96", + "type": "uint160" + }, + { + "internalType": "int24", + "name": "tick", + "type": "int24" + }, + { + "internalType": "uint16", + "name": "observationIndex", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "observationCardinality", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "observationCardinalityNext", + "type": "uint16" + }, + { + "internalType": "uint8", + "name": "feeProtocol", + "type": "uint8" + }, + { + "internalType": "bool", + "name": "unlocked", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "int24", + "name": "tickLower", + "type": "int24" + }, + { + "internalType": "int24", + "name": "tickUpper", + "type": "int24" + } + ], + "name": "snapshotCumulativesInside", + "outputs": [ + { + "internalType": "int56", + "name": "tickCumulativeInside", + "type": "int56" + }, + { + "internalType": "uint160", + "name": "secondsPerLiquidityInsideX128", + "type": "uint160" + }, + { + "internalType": "uint32", + "name": "secondsInside", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "bool", + "name": "zeroForOne", + "type": "bool" + }, + { + "internalType": "int256", + "name": "amountSpecified", + "type": "int256" + }, + { + "internalType": "uint160", + "name": "sqrtPriceLimitX96", + "type": "uint160" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "swap", + "outputs": [ + { + "internalType": "int256", + "name": "amount0", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1", + "type": "int256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "int16", + "name": "wordPosition", + "type": "int16" + } + ], + "name": "tickBitmap", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "tickSpacing", + "outputs": [ + { + "internalType": "int24", + "name": "", + "type": "int24" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "int24", + "name": "tick", + "type": "int24" + } + ], + "name": "ticks", + "outputs": [ + { + "internalType": "uint128", + "name": "liquidityGross", + "type": "uint128" + }, + { + "internalType": "int128", + "name": "liquidityNet", + "type": "int128" + }, + { + "internalType": "uint256", + "name": "feeGrowthOutside0X128", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "feeGrowthOutside1X128", + "type": "uint256" + }, + { + "internalType": "int56", + "name": "tickCumulativeOutside", + "type": "int56" + }, + { + "internalType": "uint160", + "name": "secondsPerLiquidityOutsideX128", + "type": "uint160" + }, + { + "internalType": "uint32", + "name": "secondsOutside", + "type": "uint32" + }, + { + "internalType": "bool", + "name": "initialized", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "token0", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "token1", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } +] \ No newline at end of file diff --git a/abis/v1/empty.json b/abis/v1/empty.json new file mode 100644 index 0000000..0637a08 --- /dev/null +++ b/abis/v1/empty.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/abis/v5/DLPRegistryImplementation.json b/abis/v5/DLPRegistryImplementation.json index 968eb23..05bd658 100644 --- a/abis/v5/DLPRegistryImplementation.json +++ b/abis/v5/DLPRegistryImplementation.json @@ -1,58 +1,187 @@ [ - { "inputs": [], "stateMutability": "nonpayable", "type": "constructor" }, - { "inputs": [], "name": "AccessControlBadConfirmation", "type": "error" }, + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "AccessControlBadConfirmation", + "type": "error" + }, { "inputs": [ - { "internalType": "address", "name": "account", "type": "address" }, - { "internalType": "bytes32", "name": "neededRole", "type": "bytes32" } + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "neededRole", + "type": "bytes32" + } ], "name": "AccessControlUnauthorizedAccount", "type": "error" }, { "inputs": [ - { "internalType": "address", "name": "target", "type": "address" } + { + "internalType": "address", + "name": "target", + "type": "address" + } ], "name": "AddressEmptyCode", "type": "error" }, - { "inputs": [], "name": "DlpAddressCannotBeChanged", "type": "error" }, - { "inputs": [], "name": "DlpAlreadyVerified", "type": "error" }, - { "inputs": [], "name": "DlpTokenNotSet", "type": "error" }, + { + "inputs": [], + "name": "DlpAddressCannotBeChanged", + "type": "error" + }, + { + "inputs": [], + "name": "DlpLpTokenIdNotSet", + "type": "error" + }, + { + "inputs": [], + "name": "DlpTokenNotSet", + "type": "error" + }, { "inputs": [ - { "internalType": "address", "name": "implementation", "type": "address" } + { + "internalType": "address", + "name": "implementation", + "type": "address" + } ], "name": "ERC1967InvalidImplementation", "type": "error" }, - { "inputs": [], "name": "ERC1967NonPayable", "type": "error" }, - { "inputs": [], "name": "EnforcedPause", "type": "error" }, - { "inputs": [], "name": "EpochDlpScoreAlreadySaved", "type": "error" }, - { "inputs": [], "name": "EpochNotEnded", "type": "error" }, - { "inputs": [], "name": "EpochRewardsAlreadyDistributed", "type": "error" }, - { "inputs": [], "name": "ExpectedPause", "type": "error" }, - { "inputs": [], "name": "FailedInnerCall", "type": "error" }, - { "inputs": [], "name": "InvalidAddress", "type": "error" }, - { "inputs": [], "name": "InvalidDepositAmount", "type": "error" }, - { "inputs": [], "name": "InvalidDlpId", "type": "error" }, - { "inputs": [], "name": "InvalidDlpStatus", "type": "error" }, - { "inputs": [], "name": "InvalidInitialization", "type": "error" }, - { "inputs": [], "name": "InvalidName", "type": "error" }, - { "inputs": [], "name": "InvalidParam", "type": "error" }, - { "inputs": [], "name": "LastEpochMustBeFinalized", "type": "error" }, - { "inputs": [], "name": "NotDlpOwner", "type": "error" }, - { "inputs": [], "name": "NotInitializing", "type": "error" }, - { "inputs": [], "name": "ReentrancyGuardReentrantCall", "type": "error" }, - { "inputs": [], "name": "TransferFailed", "type": "error" }, - { "inputs": [], "name": "UUPSUnauthorizedCallContext", "type": "error" }, - { - "inputs": [ - { "internalType": "bytes32", "name": "slot", "type": "bytes32" } + { + "inputs": [], + "name": "ERC1967NonPayable", + "type": "error" + }, + { + "inputs": [], + "name": "EnforcedPause", + "type": "error" + }, + { + "inputs": [], + "name": "ExpectedPause", + "type": "error" + }, + { + "inputs": [], + "name": "FailedInnerCall", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidAddress", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidDepositAmount", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidDlpStatus", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidDlpVerification", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidInitialization", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidLpTokenId", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidName", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTokenAddress", + "type": "error" + }, + { + "inputs": [], + "name": "LastEpochMustBeFinalized", + "type": "error" + }, + { + "inputs": [], + "name": "NotDlpOwner", + "type": "error" + }, + { + "inputs": [], + "name": "NotInitializing", + "type": "error" + }, + { + "inputs": [], + "name": "ReentrancyGuardReentrantCall", + "type": "error" + }, + { + "inputs": [], + "name": "TransferFailed", + "type": "error" + }, + { + "inputs": [], + "name": "UUPSUnauthorizedCallContext", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "slot", + "type": "bytes32" + } ], "name": "UUPSUnsupportedProxiableUUID", "type": "error" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "dlpId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "lpTokenId", + "type": "uint256" + } + ], + "name": "DlpLpTokenIdUpdated", + "type": "event" + }, { "anonymous": false, "inputs": [ @@ -140,19 +269,6 @@ "name": "DlpStatusUpdated", "type": "event" }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "newDlpSubEligibilityThreshold", - "type": "uint256" - } - ], - "name": "DlpSubEligibilityThresholdUpdated", - "type": "event" - }, { "anonymous": false, "inputs": [ @@ -227,6 +343,25 @@ "name": "DlpUpdated", "type": "event" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "dlpId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "verificationBlockNumber", + "type": "uint256" + } + ], + "name": "DlpVerificationBlockUpdated", + "type": "event" + }, { "anonymous": false, "inputs": [ @@ -376,27 +511,49 @@ { "inputs": [], "name": "DEFAULT_ADMIN_ROLE", - "outputs": [{ "internalType": "bytes32", "name": "", "type": "bytes32" }], + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "MAINTAINER_ROLE", - "outputs": [{ "internalType": "bytes32", "name": "", "type": "bytes32" }], + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "UPGRADE_INTERFACE_VERSION", - "outputs": [{ "internalType": "string", "name": "", "type": "string" }], + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], "stateMutability": "view", "type": "function" }, { "inputs": [ - { "internalType": "uint256", "name": "dlpId", "type": "uint256" } + { + "internalType": "uint256", + "name": "dlpId", + "type": "uint256" + } ], "name": "deregisterDlp", "outputs": [], @@ -405,22 +562,38 @@ }, { "inputs": [ - { "internalType": "address", "name": "dlpAddress", "type": "address" } + { + "internalType": "address", + "name": "dlpAddress", + "type": "address" + } ], "name": "dlpIds", "outputs": [ - { "internalType": "uint256", "name": "dlpId", "type": "uint256" } + { + "internalType": "uint256", + "name": "dlpId", + "type": "uint256" + } ], "stateMutability": "view", "type": "function" }, { "inputs": [ - { "internalType": "string", "name": "dlpName", "type": "string" } + { + "internalType": "string", + "name": "dlpName", + "type": "string" + } ], "name": "dlpNameToId", "outputs": [ - { "internalType": "uint256", "name": "dlpId", "type": "uint256" } + { + "internalType": "uint256", + "name": "dlpId", + "type": "uint256" + } ], "stateMutability": "view", "type": "function" @@ -428,19 +601,33 @@ { "inputs": [], "name": "dlpRegistrationDepositAmount", - "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], "stateMutability": "view", "type": "function" }, { "inputs": [ - { "internalType": "uint256", "name": "dlpId", "type": "uint256" } + { + "internalType": "uint256", + "name": "dlpId", + "type": "uint256" + } ], "name": "dlps", "outputs": [ { "components": [ - { "internalType": "uint256", "name": "id", "type": "uint256" }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, { "internalType": "address", "name": "dlpAddress", @@ -461,10 +648,26 @@ "name": "treasuryAddress", "type": "address" }, - { "internalType": "string", "name": "name", "type": "string" }, - { "internalType": "string", "name": "iconUrl", "type": "string" }, - { "internalType": "string", "name": "website", "type": "string" }, - { "internalType": "string", "name": "metadata", "type": "string" }, + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "iconUrl", + "type": "string" + }, + { + "internalType": "string", + "name": "website", + "type": "string" + }, + { + "internalType": "string", + "name": "metadata", + "type": "string" + }, { "internalType": "uint256", "name": "registrationBlockNumber", @@ -480,7 +683,16 @@ "name": "status", "type": "uint8" }, - { "internalType": "bool", "name": "isVerified", "type": "bool" } + { + "internalType": "uint256", + "name": "lpTokenId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "verificationBlockNumber", + "type": "uint256" + } ], "internalType": "struct IDLPRegistry.DlpInfo", "name": "", @@ -492,13 +704,21 @@ }, { "inputs": [ - { "internalType": "address", "name": "dlpAddress", "type": "address" } + { + "internalType": "address", + "name": "dlpAddress", + "type": "address" + } ], "name": "dlpsByAddress", "outputs": [ { "components": [ - { "internalType": "uint256", "name": "id", "type": "uint256" }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, { "internalType": "address", "name": "dlpAddress", @@ -519,10 +739,26 @@ "name": "treasuryAddress", "type": "address" }, - { "internalType": "string", "name": "name", "type": "string" }, - { "internalType": "string", "name": "iconUrl", "type": "string" }, - { "internalType": "string", "name": "website", "type": "string" }, - { "internalType": "string", "name": "metadata", "type": "string" }, + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "iconUrl", + "type": "string" + }, + { + "internalType": "string", + "name": "website", + "type": "string" + }, + { + "internalType": "string", + "name": "metadata", + "type": "string" + }, { "internalType": "uint256", "name": "registrationBlockNumber", @@ -538,9 +774,18 @@ "name": "status", "type": "uint8" }, - { "internalType": "bool", "name": "isVerified", "type": "bool" } - ], - "internalType": "struct IDLPRegistry.DlpInfo", + { + "internalType": "uint256", + "name": "lpTokenId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "verificationBlockNumber", + "type": "uint256" + } + ], + "internalType": "struct IDLPRegistry.DlpInfo", "name": "", "type": "tuple" } @@ -550,13 +795,21 @@ }, { "inputs": [ - { "internalType": "string", "name": "dlpName", "type": "string" } + { + "internalType": "string", + "name": "dlpName", + "type": "string" + } ], "name": "dlpsByName", "outputs": [ { "components": [ - { "internalType": "uint256", "name": "id", "type": "uint256" }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, { "internalType": "address", "name": "dlpAddress", @@ -577,10 +830,26 @@ "name": "treasuryAddress", "type": "address" }, - { "internalType": "string", "name": "name", "type": "string" }, - { "internalType": "string", "name": "iconUrl", "type": "string" }, - { "internalType": "string", "name": "website", "type": "string" }, - { "internalType": "string", "name": "metadata", "type": "string" }, + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "iconUrl", + "type": "string" + }, + { + "internalType": "string", + "name": "website", + "type": "string" + }, + { + "internalType": "string", + "name": "metadata", + "type": "string" + }, { "internalType": "uint256", "name": "registrationBlockNumber", @@ -596,7 +865,16 @@ "name": "status", "type": "uint8" }, - { "internalType": "bool", "name": "isVerified", "type": "bool" } + { + "internalType": "uint256", + "name": "lpTokenId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "verificationBlockNumber", + "type": "uint256" + } ], "internalType": "struct IDLPRegistry.DlpInfo", "name": "", @@ -609,30 +887,45 @@ { "inputs": [], "name": "dlpsCount", - "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "eligibleDlpsLimit", - "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], "stateMutability": "view", "type": "function" }, { "inputs": [ - { "internalType": "uint256", "name": "index", "type": "uint256" } + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + } ], "name": "eligibleDlpsListAt", - "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "eligibleDlpsListCount", - "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], "stateMutability": "view", "type": "function" }, @@ -640,24 +933,46 @@ "inputs": [], "name": "eligibleDlpsListValues", "outputs": [ - { "internalType": "uint256[]", "name": "", "type": "uint256[]" } + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } ], "stateMutability": "view", "type": "function" }, { "inputs": [ - { "internalType": "bytes32", "name": "role", "type": "bytes32" } + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } ], "name": "getRoleAdmin", - "outputs": [{ "internalType": "bytes32", "name": "", "type": "bytes32" }], + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], "stateMutability": "view", "type": "function" }, { "inputs": [ - { "internalType": "bytes32", "name": "role", "type": "bytes32" }, - { "internalType": "address", "name": "account", "type": "address" } + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } ], "name": "grantRole", "outputs": [], @@ -666,23 +981,64 @@ }, { "inputs": [ - { "internalType": "bytes32", "name": "role", "type": "bytes32" }, - { "internalType": "address", "name": "account", "type": "address" } + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } ], "name": "hasRole", - "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], "stateMutability": "view", "type": "function" }, { "inputs": [ - { "internalType": "address", "name": "ownerAddress", "type": "address" } + { + "internalType": "address", + "name": "ownerAddress", + "type": "address" + } ], "name": "initialize", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [ + { + "internalType": "address", + "name": "dlpRootCoreAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "startDlpId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "endDlpId", + "type": "uint256" + } + ], + "name": "migrateDlpData", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [], "name": "pause", @@ -693,14 +1049,26 @@ { "inputs": [], "name": "paused", - "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "proxiableUUID", - "outputs": [{ "internalType": "bytes32", "name": "", "type": "bytes32" }], + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], "stateMutability": "view", "type": "function" }, @@ -723,10 +1091,26 @@ "name": "treasuryAddress", "type": "address" }, - { "internalType": "string", "name": "name", "type": "string" }, - { "internalType": "string", "name": "iconUrl", "type": "string" }, - { "internalType": "string", "name": "website", "type": "string" }, - { "internalType": "string", "name": "metadata", "type": "string" } + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "iconUrl", + "type": "string" + }, + { + "internalType": "string", + "name": "website", + "type": "string" + }, + { + "internalType": "string", + "name": "metadata", + "type": "string" + } ], "internalType": "struct IDLPRegistry.DlpRegistration", "name": "registrationInfo", @@ -740,7 +1124,11 @@ }, { "inputs": [ - { "internalType": "bytes32", "name": "role", "type": "bytes32" }, + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, { "internalType": "address", "name": "callerConfirmation", @@ -754,8 +1142,16 @@ }, { "inputs": [ - { "internalType": "bytes32", "name": "role", "type": "bytes32" }, - { "internalType": "address", "name": "account", "type": "address" } + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } ], "name": "revokeRole", "outputs": [], @@ -764,10 +1160,20 @@ }, { "inputs": [ - { "internalType": "bytes4", "name": "interfaceId", "type": "bytes4" } + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } ], "name": "supportsInterface", - "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], "stateMutability": "view", "type": "function" }, @@ -775,7 +1181,11 @@ "inputs": [], "name": "treasury", "outputs": [ - { "internalType": "contract ITreasury", "name": "", "type": "address" } + { + "internalType": "contract ITreasury", + "name": "", + "type": "address" + } ], "stateMutability": "view", "type": "function" @@ -789,7 +1199,24 @@ }, { "inputs": [ - { "internalType": "uint256", "name": "dlpId", "type": "uint256" }, + { + "internalType": "uint256", + "name": "dlpId", + "type": "uint256" + } + ], + "name": "unverifyDlp", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "dlpId", + "type": "uint256" + }, { "components": [ { @@ -807,10 +1234,26 @@ "name": "treasuryAddress", "type": "address" }, - { "internalType": "string", "name": "name", "type": "string" }, - { "internalType": "string", "name": "iconUrl", "type": "string" }, - { "internalType": "string", "name": "website", "type": "string" }, - { "internalType": "string", "name": "metadata", "type": "string" } + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "iconUrl", + "type": "string" + }, + { + "internalType": "string", + "name": "website", + "type": "string" + }, + { + "internalType": "string", + "name": "metadata", + "type": "string" + } ], "internalType": "struct IDLPRegistry.DlpRegistration", "name": "dlpUpdateInfo", @@ -837,8 +1280,21 @@ }, { "inputs": [ - { "internalType": "uint256", "name": "dlpId", "type": "uint256" }, - { "internalType": "address", "name": "tokenAddress", "type": "address" } + { + "internalType": "uint256", + "name": "dlpId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "lpTokenId", + "type": "uint256" + } ], "name": "updateDlpToken", "outputs": [], @@ -847,10 +1303,46 @@ }, { "inputs": [ - { "internalType": "uint256", "name": "dlpId", "type": "uint256" }, - { "internalType": "bool", "name": "isVerified", "type": "bool" } + { + "internalType": "uint256", + "name": "dlpId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "lpTokenId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "verificationBlockNumber", + "type": "uint256" + } + ], + "name": "updateDlpTokenAndVerification", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "dlpId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "verificationBlockNumber", + "type": "uint256" + } ], - "name": "updateDlpVerification", + "name": "updateDlpVerificationBlock", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -888,7 +1380,11 @@ "name": "newImplementation", "type": "address" }, - { "internalType": "bytes", "name": "data", "type": "bytes" } + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } ], "name": "upgradeToAndCall", "outputs": [], @@ -899,7 +1395,11 @@ "inputs": [], "name": "vanaEpoch", "outputs": [ - { "internalType": "contract IVanaEpoch", "name": "", "type": "address" } + { + "internalType": "contract IVanaEpoch", + "name": "", + "type": "address" + } ], "stateMutability": "view", "type": "function" @@ -907,8 +1407,14 @@ { "inputs": [], "name": "version", - "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], "stateMutability": "pure", "type": "function" } -] +] \ No newline at end of file diff --git a/config/moksha.json b/config/moksha.json index 0f2a423..29f8349 100644 --- a/config/moksha.json +++ b/config/moksha.json @@ -21,6 +21,9 @@ "queryEngine": true, "dataRefinerRegistry": true, "dataPermission": true + }, + "uniswap": { + "v3": true } }, "initParams": { @@ -36,6 +39,7 @@ {"startBlock": 2718338, "endBlock": 2772937}, {"startBlock": 2772938, "endBlock": 2827537}, {"startBlock": 2827538, "endBlock": 2882137} - ] + ], + "dlps" : [] } diff --git a/config/uniswap/moksha/chain.ts b/config/uniswap/moksha/chain.ts new file mode 100644 index 0000000..aab442c --- /dev/null +++ b/config/uniswap/moksha/chain.ts @@ -0,0 +1,44 @@ +import { Address, BigDecimal, BigInt } from '@graphprotocol/graph-ts' + +export const FACTORY_ADDRESS = '0x7067eb594d6dc6a5ad33c3fcfca7183f369bc2e8' + +export const REFERENCE_TOKEN = '0xbccc4b4c6530f82fe309c5e845e50b5e9c89f2ad' // WVANA +export const STABLE_TOKEN_POOL = '0x124ad2057083b7db2346f3bdc4e6f105dbcb1545' // USDC Pool + +export const TVL_MULTIPLIER_THRESHOLD = '2' +export const MATURE_MARKET = '1000000' +export const MINIMUM_NATIVE_LOCKED = BigDecimal.fromString('20') + +export const ROLL_DELETE_HOUR = 768 +export const ROLL_DELETE_MINUTE = 1680 + +export const ROLL_DELETE_HOUR_LIMITER = BigInt.fromI32(500) +export const ROLL_DELETE_MINUTE_LIMITER = BigInt.fromI32(1000) + +// token where amounts should contribute to tracked volume and liquidity +export const WHITELIST_TOKENS: string[] = [ + REFERENCE_TOKEN, // WVANA + '0xb39a50b5806039c82932bb96cefbcbc61231045c', // USDC + '0x01079c78199e05d44bbff9e50dbdf765489f16e1', // USDT + '0xb18a68588e4551b880011af27df5347b99b444c2', // VOL + '0xf5a960f8f0d04aaedc44f2619977a2b7de9cef09', // DNA + '0xf379a80f0585e57fd5aebb29d8cafac60f8f54c3', // WDUDE +] + +export const STABLE_COINS: string[] = [ + '0xb39a50b5806039c82932bb96cefbcbc61231045c', // USDC + '0x01079c78199e05d44bbff9e50dbdf765489f16e1', // USDT +] + +export const SKIP_POOLS: string[] = [] + +export const POOL_MAPINGS: Array = [] + +export class TokenDefinition { + address: Address + symbol: string + name: string + decimals: BigInt +} + +export const STATIC_TOKEN_DEFINITIONS: TokenDefinition[] = [] diff --git a/config/uniswap/vana/chain.ts b/config/uniswap/vana/chain.ts new file mode 100644 index 0000000..5a39721 --- /dev/null +++ b/config/uniswap/vana/chain.ts @@ -0,0 +1,49 @@ +import { Address, BigDecimal, BigInt } from '@graphprotocol/graph-ts' + +export const FACTORY_ADDRESS = '0xc2a0d530e57b1275fbce908031da636f95ea1e38' + +export const REFERENCE_TOKEN = '0x00eddd9621fb08436d0331c149d1690909a5906d' // WVANA +export const STABLE_TOKEN_POOL = '0x850e454ddebf9f61ef5a86a032c857e0e47c4fa9' // USDC.e Pool + +export const TVL_MULTIPLIER_THRESHOLD = '2' +export const MATURE_MARKET = '1000000' +export const MINIMUM_NATIVE_LOCKED = BigDecimal.fromString('20') + +export const ROLL_DELETE_HOUR = 768 +export const ROLL_DELETE_MINUTE = 1680 + +export const ROLL_DELETE_HOUR_LIMITER = BigInt.fromI32(500) +export const ROLL_DELETE_MINUTE_LIMITER = BigInt.fromI32(1000) + +// token where amounts should contribute to tracked volume and liquidity +export const WHITELIST_TOKENS: string[] = [ + REFERENCE_TOKEN, // WVANA + '0xf1815bd50389c46847f0bda824ec8da914045d14', // USDC.e + '0x2f6f07cdcf3588944bf4c42ac74ff24bf56e7590', // WETH + '0xf23e379b2fd945f8c0a4f410cb6ef9398bf022d6', // KDAT + '0x84f8dc1ada73298281387e62616470f3dd5df2f6', // SIX + '0x0cc1bc0131dd9782e65ca0319cd3a60eba3a932d', // VFSN + '0xeb68ef0550a5532447da0fea4f0ed9f804803b8b', // VOL + '0x1becf440e8bcfc78cdfd45f29f7b1dc04df7777c', // FIN + '0xf8f97a79a3fa77104fab4814e3ed93899777de0d', // GDP + '0xd561ce710ff7ce7d93fd7b1f0ff1b1989fe7256e', // MIND + '0xc7a473434290671cffea503ca4b7b160f929c1ec', // DNA + '0x579c80e02ef43345ce3a4c833c49da9730bd0f3f', // $PRIME +] + +export const STABLE_COINS: string[] = [ + '0xf1815bd50389c46847f0bda824ec8da914045d14', // USDC.e +] + +export const SKIP_POOLS: string[] = [] + +export const POOL_MAPINGS: Array = [] + +export class TokenDefinition { + address: Address + symbol: string + name: string + decimals: BigInt +} + +export const STATIC_TOKEN_DEFINITIONS: TokenDefinition[] = [] \ No newline at end of file diff --git a/config/vana.json b/config/vana.json index a391713..0eb4212 100644 --- a/config/vana.json +++ b/config/vana.json @@ -21,6 +21,9 @@ "queryEngine": true, "dataRefinerRegistry": true, "dataPermission": true + }, + "uniswap": { + "v3": true } }, "initParams": { @@ -36,5 +39,38 @@ {"startBlock": 1893440, "endBlock": 2195839}, {"startBlock": 2195840, "endBlock": 2498239}, {"startBlock": 2498240, "endBlock": 3808640} + ], + "dlps": [ + { "id": 1, "verificationBlockNumber": 0 }, + { "id": 2, "verificationBlockNumber": 0 }, + { "id": 3, "verificationBlockNumber": 0 }, + { "id": 4, "verificationBlockNumber": 3720671 }, + { "id": 5, "verificationBlockNumber": 0 }, + { "id": 6, "verificationBlockNumber": 0 }, + { "id": 7, "verificationBlockNumber": 0 }, + { "id": 8, "verificationBlockNumber": 0 }, + { "id": 9, "verificationBlockNumber": 3633774 }, + { "id": 10, "verificationBlockNumber": 3500771 }, + { "id": 11, "verificationBlockNumber": 3711654 }, + { "id": 12, "verificationBlockNumber": 0 }, + { "id": 13, "verificationBlockNumber": 3633417 }, + { "id": 14, "verificationBlockNumber": 0 }, + { "id": 15, "verificationBlockNumber": 0 }, + { "id": 16, "verificationBlockNumber": 0 }, + { "id": 17, "verificationBlockNumber": 3659295 }, + { "id": 18, "verificationBlockNumber": 0 }, + { "id": 19, "verificationBlockNumber": 0 }, + { "id": 20, "verificationBlockNumber": 0 }, + { "id": 21, "verificationBlockNumber": 0 }, + { "id": 22, "verificationBlockNumber": 0 }, + { "id": 23, "verificationBlockNumber": 0 }, + { "id": 24, "verificationBlockNumber": 0 }, + { "id": 25, "verificationBlockNumber": 0 }, + { "id": 26, "verificationBlockNumber": 0 }, + { "id": 27, "verificationBlockNumber": 0 }, + { "id": 28, "verificationBlockNumber": 0 }, + { "id": 29, "verificationBlockNumber": 0 }, + { "id": 30, "verificationBlockNumber": 0 }, + { "id": 31, "verificationBlockNumber": 0 } ] } \ No newline at end of file diff --git a/package.json b/package.json index ec3adf2..c1db807 100644 --- a/package.json +++ b/package.json @@ -5,12 +5,12 @@ "codegen": "npx graph codegen", "build": "npx graph build", "prepare:moksha:thegraph": "cp ./subgraph.vana-moksha.yaml ./subgraph.yaml && mustache config/moksha.json src/mapping.ts.template > src/mapping.ts", - "prepare:moksha": "cp ./subgraph.moksha.yaml ./subgraph.yaml && mustache config/moksha.json src/mapping.ts.template > src/mapping.ts", + "prepare:moksha": "cp ./subgraph.moksha.yaml ./subgraph.yaml && yarn manual-copy-moksha && mustache config/moksha.json src/mapping.ts.template > src/mapping.ts", "deploy:moksha": "node ./scripts/deploy.js moksha", "delete:moksha": "node ./scripts/delete.js moksha", "tag:moksha": "node ./scripts/tag.js moksha", "untag:moksha": "node ./scripts/untag.js moksha", - "prepare:vana": "cp ./subgraph.vana.yaml ./subgraph.yaml && mustache config/vana.json src/mapping.ts.template > src/mapping.ts", + "prepare:vana": "cp ./subgraph.vana.yaml ./subgraph.yaml && yarn manual-copy-vana && mustache config/vana.json src/mapping.ts.template > src/mapping.ts", "deploy:vana": "node ./scripts/deploy.js vana", "delete:vana": "node ./scripts/delete.js vana", "tag:vana": "node ./scripts/tag.js vana", @@ -25,7 +25,9 @@ "format:unsafe": "biome check --write --unsafe", "create-local": "npx graph create --node http://localhost:8020/ moksha", "remove-local": "npx graph remove --node http://localhost:8020/ moksha", - "deploy-local": "npx graph deploy --node http://localhost:8020/ --ipfs http://localhost:5001 moksha" + "deploy-local": "npx graph deploy --node http://localhost:8020/ --ipfs http://localhost:5001 moksha", + "manual-copy-moksha": "cp -r config/uniswap/moksha/chain.ts src/uniswap/common/chain.ts", + "manual-copy-vana": "cp -r config/uniswap/vana/chain.ts src/uniswap/common/chain.ts" }, "dependencies": { "@graphprotocol/graph-cli": "0.95.0", diff --git a/schema.graphql b/schema.graphql index 3b5dc0b..81bb18c 100644 --- a/schema.graphql +++ b/schema.graphql @@ -6,7 +6,7 @@ type User @entity(immutable: false) { "All permissions granted by this user" permissions: [Permission!]! @derivedFrom(field: "grantor") "All servers trusted by this user" - trustedServers: [TrustedServer!]! @derivedFrom(field: "user") + servers: [Server!]! @derivedFrom(field: "user") } type UserTotals @entity(immutable: false) { @@ -32,11 +32,8 @@ type Dlp @entity(immutable: false) { metadata: String token: Bytes refiners: [Refiner!]! @derivedFrom(field: "dlp") - isVerified: Boolean performances: [DlpPerformance!]! @derivedFrom(field: "dlp") - isRewardEligible: Boolean - rewardEligibleAt: BigInt - rewardEligibleAtBlock: BigInt + verificationBlockNumber: BigInt totals: Totals } @@ -59,11 +56,6 @@ type Epoch @entity(immutable: false) { performances: [DlpPerformance!]! @derivedFrom(field: "epoch") } -type FileOwner @entity(immutable: false) { - id: ID! - ownerAddress: Bytes! -} - type DataRegistryProof @entity(immutable: false) { id: ID! user: User # Optional for v1 @@ -82,6 +74,8 @@ type Totals @entity(immutable: false) { totalFileContributions: BigInt! uniqueFileContributors: BigInt! + + dataAccessFees: BigDecimal! } type DlpList @entity(immutable: false) { @@ -137,6 +131,10 @@ type DlpPerformance @entity(immutable: false) { createdAtBlock: BigInt! } +type PerformanceDlpEpochUser @entity(immutable: false) { + id: ID! +} + type File @entity(immutable: false) { "The unique ID of the file, equivalent to the on-chain fileId." id: ID! @@ -177,15 +175,516 @@ type Permission @entity(immutable: false) { transactionHash: Bytes! } -type TrustedServer @entity(immutable: false) { - "Composite ID: userAddress-serverAddress" +type Server @entity(immutable: false) { + "The unique ID of the Server, equivalent to the on-chain serverId" id: ID! "The user who trusts the server." user: User! "The server's address (ID)." serverAddress: Bytes! "The URL of the server." + publicKey: String! + "The URL of the server." serverUrl: String! "Timestamp of when the trust was established." trustedAt: BigInt! } + +type Factory @entity { + # factory address + id: ID! + # amount of pools created + poolCount: BigInt! + # amoutn of transactions all time + txCount: BigInt! + # total volume all time in derived USD + totalVolumeUSD: BigDecimal! + # total volume all time in derived ETH + totalVolumeETH: BigDecimal! + # total swap fees all time in USD + totalFeesUSD: BigDecimal! + # total swap fees all time in USD + totalFeesETH: BigDecimal! + # all volume even through less reliable USD values + untrackedVolumeUSD: BigDecimal! + # TVL derived in USD + totalValueLockedUSD: BigDecimal! + # TVL derived in ETH + totalValueLockedETH: BigDecimal! + # TVL derived in USD untracked + totalValueLockedUSDUntracked: BigDecimal! + # TVL derived in ETH untracked + totalValueLockedETHUntracked: BigDecimal! + + # current owner of the factory + owner: ID! +} + +# stores for USD calculations +type Bundle @entity { + id: ID! + # price of ETH in usd + ethPriceUSD: BigDecimal! +} + +type Token @entity { + # token address + id: Bytes! + # token symbol + symbol: String! + # token name + name: String! + # token decimals + decimals: BigInt! + # token total supply + totalSupply: BigInt! + # volume in token units + volume: BigDecimal! + # volume in derived USD + volumeUSD: BigDecimal! + # volume in USD even on pools with less reliable USD values + untrackedVolumeUSD: BigDecimal! + # fees in USD + feesUSD: BigDecimal! + # transactions across all pools that include this token + txCount: BigInt! + # number of pools containing this token + poolCount: BigInt! + # liquidity across all pools in token units + totalValueLocked: BigDecimal! + # liquidity across all pools in derived USD + totalValueLockedUSD: BigDecimal! + # TVL derived in USD untracked + totalValueLockedUSDUntracked: BigDecimal! + # Note: for chains where ETH is not the native token, this will be the derived + # price of that chain's native token, effectively, this should be renamed + # derivedNative + derivedETH: BigDecimal! + # pools token is in that are white listed for USD pricing + whitelistPools: [Pool!]! + # derived fields + tokenDayData: [TokenDayData!]! @derivedFrom(field: "token") +} + +type Pool @entity { + # pool address + id: Bytes! + # creation + createdAtTimestamp: BigInt! + # block pool was created at + createdAtBlockNumber: BigInt! + # token0 + token0: Token! + # token1 + token1: Token! + # fee amount + feeTier: BigInt! + # in range liquidity + liquidity: BigInt! + # current price tracker + sqrtPrice: BigInt! + # token0 per token1 + token0Price: BigDecimal! + # token1 per token0 + token1Price: BigDecimal! + # current tick + tick: BigInt + # current observation index + observationIndex: BigInt! + # all time token0 swapped + volumeToken0: BigDecimal! + # all time token1 swapped + volumeToken1: BigDecimal! + # all time USD swapped + volumeUSD: BigDecimal! + # all time USD swapped, unfiltered for unreliable USD pools + untrackedVolumeUSD: BigDecimal! + # fees in USD + feesUSD: BigDecimal! + # all time number of transactions + txCount: BigInt! + # all time fees collected token0 + collectedFeesToken0: BigDecimal! + # all time fees collected token1 + collectedFeesToken1: BigDecimal! + # all time fees collected derived USD + collectedFeesUSD: BigDecimal! + # total token 0 across all ticks + totalValueLockedToken0: BigDecimal! + # total token 1 across all ticks + totalValueLockedToken1: BigDecimal! + # tvl derived ETH + totalValueLockedETH: BigDecimal! + # tvl USD + totalValueLockedUSD: BigDecimal! + # TVL derived in USD untracked + totalValueLockedUSDUntracked: BigDecimal! + # Fields used to help derived relationship + liquidityProviderCount: BigInt! # used to detect new exchanges + # hourly snapshots of pool data + poolHourData: [PoolHourData!]! @derivedFrom(field: "pool") + # daily snapshots of pool data + poolDayData: [PoolDayData!]! @derivedFrom(field: "pool") + # derived fields + mints: [Mint!]! @derivedFrom(field: "pool") + burns: [Burn!]! @derivedFrom(field: "pool") + swaps: [Swap!]! @derivedFrom(field: "pool") + collects: [Collect!]! @derivedFrom(field: "pool") + ticks: [Tick!]! @derivedFrom(field: "pool") +} + +type Tick @entity { + # format: # + id: ID! + # pool address + poolAddress: Bytes! + # tick index + tickIdx: BigInt! + # pointer to pool + pool: Pool! + # total liquidity pool has as tick lower or upper + liquidityGross: BigInt! + # how much liquidity changes when tick crossed + liquidityNet: BigInt! + # calculated price of token0 of tick within this pool - constant + price0: BigDecimal! + # calculated price of token1 of tick within this pool - constant + price1: BigDecimal! + # created time + createdAtTimestamp: BigInt! + # created block + createdAtBlockNumber: BigInt! +} + +type Transaction @entity { + # txn hash + id: ID! + # block txn was included in + blockNumber: BigInt! + # timestamp txn was confirmed + timestamp: BigInt! + # gas used during txn execution + gasUsed: BigInt! + gasPrice: BigInt! + # derived values + mints: [Mint]! @derivedFrom(field: "transaction") + burns: [Burn]! @derivedFrom(field: "transaction") + swaps: [Swap]! @derivedFrom(field: "transaction") + flashed: [Flash]! @derivedFrom(field: "transaction") + collects: [Collect]! @derivedFrom(field: "transaction") +} + +type Mint @entity { + # transaction hash + "#" + index in mints Transaction array + id: ID! + # which txn the mint was included in + transaction: Transaction! + # time of txn + timestamp: BigInt! + # pool position is within + pool: Pool! + # allow indexing by tokens + token0: Token! + # allow indexing by tokens + token1: Token! + # owner of position where liquidity minted to + owner: Bytes! + # the address that minted the liquidity + sender: Bytes + # txn origin + origin: Bytes! # the EOA that initiated the txn + # amount of liquidity minted + amount: BigInt! + # amount of token 0 minted + amount0: BigDecimal! + # amount of token 1 minted + amount1: BigDecimal! + # derived amount based on available prices of tokens + amountUSD: BigDecimal + # lower tick of the position + tickLower: BigInt! + # upper tick of the position + tickUpper: BigInt! + # order within the txn + logIndex: BigInt +} + +type Burn @entity { + # transaction hash + "#" + index in mints Transaction array + id: ID! + # txn burn was included in + transaction: Transaction! + # pool position is within + pool: Pool! + # allow indexing by tokens + token0: Token! + # allow indexing by tokens + token1: Token! + # need this to pull recent txns for specific token or pool + timestamp: BigInt! + # owner of position where liquidity was burned + owner: Bytes + # txn origin + origin: Bytes! # the EOA that initiated the txn + # amouny of liquidity burned + amount: BigInt! + # amount of token 0 burned + amount0: BigDecimal! + # amount of token 1 burned + amount1: BigDecimal! + # derived amount based on available prices of tokens + amountUSD: BigDecimal + # lower tick of position + tickLower: BigInt! + # upper tick of position + tickUpper: BigInt! + # position within the transactions + logIndex: BigInt +} + +type Swap @entity { + # transaction hash + "#" + index in swaps Transaction array + id: ID! + # pointer to transaction + transaction: Transaction! + # timestamp of transaction + timestamp: BigInt! + # pool swap occured within + pool: Pool! + # allow indexing by tokens + token0: Token! + # allow indexing by tokens + token1: Token! + # sender of the swap + sender: Bytes! + # recipient of the swap + recipient: Bytes! + # txn origin + origin: Bytes! # the EOA that initiated the txn + # delta of token0 swapped + amount0: BigDecimal! + # delta of token1 swapped + amount1: BigDecimal! + # derived info + amountUSD: BigDecimal! + # The sqrt(price) of the pool after the swap, as a Q64.96 + sqrtPriceX96: BigInt! + # the tick after the swap + tick: BigInt! + # index within the txn + logIndex: BigInt +} + +type Collect @entity { + # transaction hash + "#" + index in collect Transaction array + id: ID! + # pointer to txn + transaction: Transaction! + # timestamp of event + timestamp: BigInt! + # pool collect occured within + pool: Pool! + # owner of position collect was performed on + owner: Bytes + # amount of token0 collected + amount0: BigDecimal! + # amount of token1 collected + amount1: BigDecimal! + # derived amount based on available prices of tokens + amountUSD: BigDecimal + # lower tick of position + tickLower: BigInt! + # uppper tick of position + tickUpper: BigInt! + # index within the txn + logIndex: BigInt +} + +type Flash @entity { + # transaction hash + "-" + index in collect Transaction array + id: ID! + # pointer to txn + transaction: Transaction! + # timestamp of event + timestamp: BigInt! + # pool collect occured within + pool: Pool! + # sender of the flash + sender: Bytes! + # recipient of the flash + recipient: Bytes! + # amount of token0 flashed + amount0: BigDecimal! + # amount of token1 flashed + amount1: BigDecimal! + # derived amount based on available prices of tokens + amountUSD: BigDecimal! + # amount token0 paid for flash + amount0Paid: BigDecimal! + # amount token1 paid for flash + amount1Paid: BigDecimal! + # index within the txn + logIndex: BigInt +} + +# Data accumulated and condensed into day stats for all of Uniswap +type UniswapDayData @entity { + # timestamp rounded to current day by dividing by 86400 + id: ID! + # timestamp rounded to current day by dividing by 86400 + date: Int! + # total daily volume in Uniswap derived in terms of ETH + volumeETH: BigDecimal! + # total daily volume in Uniswap derived in terms of USD + volumeUSD: BigDecimal! + # total daily volume in Uniswap derived in terms of USD untracked + volumeUSDUntracked: BigDecimal! + # fees in USD + feesUSD: BigDecimal! + # number of daily transactions + txCount: BigInt! + # tvl in terms of USD + tvlUSD: BigDecimal! +} + +# Data accumulated and condensed into day stats for each pool +type PoolDayData @entity { + # timestamp rounded to current day by dividing by 86400 + id: ID! + # timestamp rounded to current day by dividing by 86400 + date: Int! + # pointer to pool + pool: Pool! + # in range liquidity at end of period + liquidity: BigInt! + # current price tracker at end of period + sqrtPrice: BigInt! + # price of token0 - derived from sqrtPrice + token0Price: BigDecimal! + # price of token1 - derived from sqrtPrice + token1Price: BigDecimal! + # current tick at end of period + tick: BigInt + # tvl derived in USD at end of period + tvlUSD: BigDecimal! + # volume in token0 + volumeToken0: BigDecimal! + # volume in token1 + volumeToken1: BigDecimal! + # volume in USD + volumeUSD: BigDecimal! + # fees in USD + feesUSD: BigDecimal! + # numebr of transactions during period + txCount: BigInt! + # opening price of token0 + open: BigDecimal! + # high price of token0 + high: BigDecimal! + # low price of token0 + low: BigDecimal! + # close price of token0 + close: BigDecimal! +} + +# hourly stats tracker for pool +type PoolHourData @entity { + # format: - + id: ID! + # unix timestamp for start of hour + periodStartUnix: Int! + # pointer to pool + pool: Pool! + # in range liquidity at end of period + liquidity: BigInt! + # current price tracker at end of period + sqrtPrice: BigInt! + # price of token0 - derived from sqrtPrice + token0Price: BigDecimal! + # price of token1 - derived from sqrtPrice + token1Price: BigDecimal! + # current tick at end of period + tick: BigInt + # tvl derived in USD at end of period + tvlUSD: BigDecimal! + # volume in token0 + volumeToken0: BigDecimal! + # volume in token1 + volumeToken1: BigDecimal! + # volume in USD + volumeUSD: BigDecimal! + # fees in USD + feesUSD: BigDecimal! + # numebr of transactions during period + txCount: BigInt! + # opening price of token0 + open: BigDecimal! + # high price of token0 + high: BigDecimal! + # low price of token0 + low: BigDecimal! + # close price of token0 + close: BigDecimal! +} + +type TokenDayData @entity { + # token address concatendated with date + id: ID! + # timestamp rounded to current day by dividing by 86400 + date: Int! + # pointer to token + token: Token! + # volume in token units + volume: BigDecimal! + # volume in derived USD + volumeUSD: BigDecimal! + # volume in USD even on pools with less reliable USD values + untrackedVolumeUSD: BigDecimal! + # liquidity across all pools in token units + totalValueLocked: BigDecimal! + # liquidity across all pools in derived USD + totalValueLockedUSD: BigDecimal! + # price at end of period in USD + priceUSD: BigDecimal! + # fees in USD + feesUSD: BigDecimal! + # opening price USD + open: BigDecimal! + # high price USD + high: BigDecimal! + # low price USD + low: BigDecimal! + # close price USD + close: BigDecimal! +} + +type TokenHourData @entity { + # token address concatendated with date + id: ID! + # unix timestamp for start of hour + periodStartUnix: Int! + # pointer to token + token: Token! + # volume in token units + volume: BigDecimal! + # volume in derived USD + volumeUSD: BigDecimal! + # volume in USD even on pools with less reliable USD values + untrackedVolumeUSD: BigDecimal! + # liquidity across all pools in token units + totalValueLocked: BigDecimal! + # liquidity across all pools in derived USD + totalValueLockedUSD: BigDecimal! + # price at end of period in USD + priceUSD: BigDecimal! + # fees in USD + feesUSD: BigDecimal! + # opening price USD + open: BigDecimal! + # high price USD + high: BigDecimal! + # low price USD + low: BigDecimal! + # close price USD + close: BigDecimal! +} diff --git a/src/lib/contract/shared.ts b/src/lib/contract/shared.ts index 38883df..034e2bd 100644 --- a/src/lib/contract/shared.ts +++ b/src/lib/contract/shared.ts @@ -1,5 +1,7 @@ -import { Dlp, User } from "../../../generated/schema"; -import { getOrCreateTotals, getTotalsIdDlp } from "../entity/totals"; +import { Address, BigDecimal, BigInt, Bytes } from "@graphprotocol/graph-ts"; +import { REFERENCE_TOKEN } from "../../uniswap/common/chain"; +import { Dlp, User, Token } from "../../../generated/schema"; +import { getOrCreateTotals, getTotalsDlpId } from "../entity/totals"; export function getOrCreateUser(userId: string): User { let user = User.load(userId); @@ -15,7 +17,7 @@ export function getOrCreateDlp(dlpId: string): Dlp { if (dlp == null) { dlp = new Dlp(dlpId); - const dlpTotalsId = getTotalsIdDlp(dlpId); + const dlpTotalsId = getTotalsDlpId(dlpId); getOrCreateTotals(dlpTotalsId); // Link totals to Dlp @@ -24,3 +26,26 @@ export function getOrCreateDlp(dlpId: string): Dlp { } return dlp; } + +export function getTokenAmountInVana( + tokenAddress: Bytes, + amount: BigInt, +): BigDecimal { + if (tokenAddress == Address.zero()) { + tokenAddress = Address.fromString(REFERENCE_TOKEN); + } + + const token = Token.load(tokenAddress); + + if (!token) { + throw new Error(`Token not found: ${tokenAddress.toHex()}`); + } + + // @ts-ignore + const decimals = Number.parseInt(token.decimals.toString()) as u8; + + const precision = BigInt.fromI32(10).pow(decimals); + const decimalAmount = amount.toBigDecimal().div(precision.toBigDecimal()); + + return decimalAmount.times(token.derivedETH); +} diff --git a/src/lib/contract/shared/constants.ts b/src/lib/contract/shared/constants.ts new file mode 100644 index 0000000..90c19ef --- /dev/null +++ b/src/lib/contract/shared/constants.ts @@ -0,0 +1,18 @@ +import { BigInt as GraphBigInt } from "@graphprotocol/graph-ts"; + +/** + * Common constants used across contract handlers + */ + +// Common BigInt values +export const ONE = GraphBigInt.fromI32(1); +export const ZERO = GraphBigInt.fromI32(0); + +// Error messages +export const ERROR_NO_EPOCH = "No epoch found for block"; +export const ERROR_DLP_NOT_FOUND = "DLP not found for proof"; +export const ERROR_NO_FILE_OWNER = + "Cannot update totals: file not found or has no owner"; + +// Default values +export const DEFAULT_SCHEMA_ID = ZERO; diff --git a/src/lib/contract/shared/entity-factory.ts b/src/lib/contract/shared/entity-factory.ts new file mode 100644 index 0000000..1f9cdf8 --- /dev/null +++ b/src/lib/contract/shared/entity-factory.ts @@ -0,0 +1,58 @@ +import { BigInt as GraphBigInt } from "@graphprotocol/graph-ts"; + +/** + * Generic function to get or create an entity with initialization + * @param id - The entity ID + * @param loadFunction - Function to load the entity + * @param createFunction - Function to create the entity + * @param initFunction - Function to initialize the entity + * @returns The loaded or created entity + */ +export function getOrCreateEntity( + id: string, + loadFunction: (id: string) => T | null, + createFunction: (id: string) => T, + initFunction?: (entity: T) => void, +): T { + let entity = loadFunction(id); + if (entity == null) { + entity = createFunction(id); + if (initFunction) { + initFunction(entity); + } + // Note: entities should be saved in the initFunction or by the caller + } + return entity; +} + +/** + * Generic initialization function for entities with zero BigInt fields + * @param entity - The entity to initialize + * @param fields - Array of field names to initialize with zero + */ +export function initializeZeroFields(entity: any, fields: string[]): void { + for (let i = 0; i < fields.length; i++) { + entity[fields[i]] = GraphBigInt.zero(); + } +} + +/** + * Creates an entity with the save operation + * @param id - The entity ID + * @param entityConstructor - Constructor function for the entity + * @param initFunction - Optional initialization function + * @returns The created and saved entity + */ +export function createAndSaveEntity( + id: string, + entityConstructor: (id: string) => T, + initFunction?: (entity: T) => void, +): T { + const entity = entityConstructor(id); + if (initFunction) { + initFunction(entity); + } + // Assuming all entities have a save method + (entity as any).save(); + return entity; +} diff --git a/src/lib/contract/shared/entity-utils.ts b/src/lib/contract/shared/entity-utils.ts new file mode 100644 index 0000000..92a4088 --- /dev/null +++ b/src/lib/contract/shared/entity-utils.ts @@ -0,0 +1,55 @@ +import { log } from "@graphprotocol/graph-ts"; + +/** + * Generic entity loader with error handling + * @param entityType - The entity type (for logging) + * @param entityId - The entity ID to load + * @param loadFunction - Function to load the entity + * @param context - Optional context for error logging + * @returns The loaded entity or null if not found + */ +export function loadEntityWithErrorHandling( + entityType: string, + entityId: string, + loadFunction: (id: string) => T | null, + context?: string, +): T | null { + const entity = loadFunction(entityId); + if (entity == null) { + const message = context + ? `${entityType} not found for ${context}: {}` + : `${entityType} not found: {}`; + log.error(message, [entityId]); + } + return entity; +} + +/** + * Safely adds an item to an array if it doesn't already exist + * @param array - The array to add to + * @param item - The item to add + * @returns True if item was added, false if it already existed + */ +export function addToArrayIfNotExists(array: T[], item: T): boolean { + const index = array.indexOf(item); + if (index === -1) { + array.push(item); + return true; + } + return false; +} + +/** + * Safely removes an item from an array + * @param array - The array to remove from + * @param item - The item to remove + * @returns True if item was removed, false if it wasn't found + */ +export function removeFromArray(array: T[], item: T): boolean { + const index = array.indexOf(item); + if (index !== -1) { + array.splice(index, 1); + return true; + } + return false; +} diff --git a/src/lib/contract/shared/event-utils.ts b/src/lib/contract/shared/event-utils.ts new file mode 100644 index 0000000..df4c9aa --- /dev/null +++ b/src/lib/contract/shared/event-utils.ts @@ -0,0 +1,78 @@ +import { log, ethereum, BigInt as GraphBigInt } from "@graphprotocol/graph-ts"; + +/** + * Standard logging format for all contract events + * @param eventName - The name of the event being handled + * @param transactionHash - The transaction hash + */ +export function logEventWithTxHash( + eventName: string, + transactionHash: string, +): void { + log.info("Handling {} with transaction hash: {}", [ + eventName, + transactionHash, + ]); +} + +/** + * Logs an entity not found error with context + * @param entityType - The type of entity (e.g., "DLP", "User", "Epoch") + * @param entityId - The ID of the entity that was not found + * @param context - Additional context about where the error occurred + */ +export function logEntityNotFound( + entityType: string, + entityId: string, + context?: string, +): void { + const message = context + ? `${entityType} not found for ${context}: {}` + : `${entityType} not found: {}`; + log.error(message, [entityId]); +} + +/** + * Sets common blockchain metadata fields on an entity + * @param entity - The entity to set metadata on + * @param block - The block information + * @param transaction - The transaction information + * @param logIndex - Optional log index for the event + */ +export function setBlockchainMetadata( + entity: any, + block: ethereum.Block, + transaction: ethereum.Transaction, + logIndex?: GraphBigInt, +): void { + entity.createdAt = block.timestamp; + entity.createdAtBlock = block.number; + entity.createdTxHash = transaction.hash; + + if (logIndex) { + entity.logIndex = logIndex; + } +} + +/** + * Creates a composite ID from multiple parts + * @param parts - Array of string parts to join + * @param separator - Separator to use (defaults to "-") + * @returns The composite ID + */ +export function createCompositeId(parts: string[], separator = "-"): string { + return parts.join(separator); +} + +/** + * Creates a transaction-based ID + * @param transactionHash - The transaction hash + * @param logIndex - The log index + * @returns The transaction-based ID + */ +export function createTransactionId( + transactionHash: string, + logIndex: GraphBigInt, +): string { + return `${transactionHash}-${logIndex.toString()}`; +} diff --git a/src/lib/contract/shared/file-handlers.ts b/src/lib/contract/shared/file-handlers.ts new file mode 100644 index 0000000..be37e1e --- /dev/null +++ b/src/lib/contract/shared/file-handlers.ts @@ -0,0 +1,58 @@ +import { BigInt as GraphBigInt, log, ethereum } from "@graphprotocol/graph-ts"; +import { File } from "../../../../generated/schema"; +import { getOrCreateUser } from "../shared"; + +/** + * Creates a new File entity from a FileAdded event + * @param fileId - The unique file ID + * @param ownerAddress - The owner's address + * @param url - The file URL + * @param block - The block information + * @param transaction - The transaction information + * @param schemaId - The schema ID (defaults to 0 for versions that don't support it) + * @returns The created File entity + */ +export function createFileFromEvent( + fileId: string, + ownerAddress: string, + url: string, + block: ethereum.Block, + transaction: ethereum.Transaction, + schemaId: GraphBigInt = GraphBigInt.fromI32(0), +): File { + log.info("Creating file {} for owner {} with transaction hash: {}", [ + fileId, + ownerAddress, + transaction.hash.toHex(), + ]); + + // Create user entity if it doesn't exist + const user = getOrCreateUser(ownerAddress); + + // Create new File entity + const file = new File(fileId); + file.owner = user.id; + file.url = url; + file.addedAtBlock = block.number; + file.addedAtTimestamp = block.timestamp; + file.transactionHash = transaction.hash; + file.schemaId = schemaId; + + file.save(); + return file; +} + +/** + * Standard logging format for DataRegistry events + * @param eventName - The name of the event being handled + * @param transactionHash - The transaction hash + */ +export function logDataRegistryEvent( + eventName: string, + transactionHash: string, +): void { + log.info("Handling DataRegistry {} with transaction hash: {}", [ + eventName, + transactionHash, + ]); +} diff --git a/src/lib/contract/shared/index.ts b/src/lib/contract/shared/index.ts new file mode 100644 index 0000000..daa25de --- /dev/null +++ b/src/lib/contract/shared/index.ts @@ -0,0 +1,15 @@ +// Re-export all shared utilities for easy importing +export * from "./file-handlers"; +export * from "./proof-handlers"; +export * from "./totals-updater"; +export * from "./constants"; +export * from "./event-utils"; +export * from "./entity-utils"; +export * from "./entity-factory"; + +// Keep the original shared.ts exports for backward compatibility +export { + getOrCreateUser, + getOrCreateDlp, + getTokenAmountInVana, +} from "../shared"; diff --git a/src/lib/contract/shared/proof-handlers.ts b/src/lib/contract/shared/proof-handlers.ts new file mode 100644 index 0000000..ae151f3 --- /dev/null +++ b/src/lib/contract/shared/proof-handlers.ts @@ -0,0 +1,60 @@ +import { + BigInt as GraphBigInt, + log, + ethereum, + Bytes, +} from "@graphprotocol/graph-ts"; +import { DataRegistryProof } from "../../../../generated/schema"; + +/** + * Creates a DataRegistryProof entity with common fields + * @param transactionHash - The transaction hash (used as entity ID) + * @param epochId - The epoch ID + * @param fileId - The file ID + * @param proofIndex - The proof index + * @param block - The block information + * @param transaction - The transaction information + * @param userId - Optional user ID (for V3+) + * @param dlpId - Optional DLP ID (for V2+) + * @param attestor - Optional attestor address (for versions that support it) + * @returns The created DataRegistryProof entity + */ +export function createDataRegistryProof( + transactionHash: string, + epochId: string, + fileId: GraphBigInt, + proofIndex: GraphBigInt, + block: ethereum.Block, + transaction: ethereum.Transaction, + userId: string | null = null, + dlpId: string | null = null, + attestor: Bytes | null = null, +): DataRegistryProof { + log.info("Creating DataRegistry proof for transaction hash: {}", [ + transactionHash, + ]); + + const proof = new DataRegistryProof(transactionHash); + + // Set common fields + proof.epoch = epochId; + proof.fileId = fileId; + proof.proofIndex = proofIndex; + proof.createdAt = block.timestamp; + proof.createdAtBlock = block.number; + proof.createdTxHash = transaction.hash; + + // Set optional fields if provided + if (userId) { + proof.user = userId; + } + if (dlpId) { + proof.dlp = dlpId; + } + if (attestor) { + proof.attestor = attestor; + } + + proof.save(); + return proof; +} diff --git a/src/lib/contract/shared/totals-updater.ts b/src/lib/contract/shared/totals-updater.ts new file mode 100644 index 0000000..27726b9 --- /dev/null +++ b/src/lib/contract/shared/totals-updater.ts @@ -0,0 +1,107 @@ +import { BigInt as GraphBigInt, log } from "@graphprotocol/graph-ts"; +import { File } from "../../../../generated/schema"; +import { + getOrCreateUserTotals, + getUserTotalsId, + getUserTotalsIdDlp, +} from "../../entity/usertotals"; +import { + getOrCreateTotals, + getTotalsDlpId, + TOTALS_ID_GLOBAL, +} from "../../entity/totals"; + +/** + * Updates global totals for file contributions + * @param userId - The user ID who contributed + */ +export function updateGlobalTotals(userId: string): void { + // Update user totals + const userTotalsId = getUserTotalsId(userId); + const userTotals = getOrCreateUserTotals(userTotalsId); + userTotals.fileContributionsCount = userTotals.fileContributionsCount.plus( + GraphBigInt.fromI32(1), + ); + userTotals.save(); + + // Update global file contribution totals + const totals = getOrCreateTotals(TOTALS_ID_GLOBAL); + totals.totalFileContributions = totals.totalFileContributions.plus( + GraphBigInt.fromI32(1), + ); + + // If this is the user's first contribution, increment unique contributors + if (userTotals.fileContributionsCount.toI32() === 1) { + totals.uniqueFileContributors = totals.uniqueFileContributors.plus( + GraphBigInt.fromI32(1), + ); + } + + totals.save(); +} + +/** + * Updates DLP-specific totals for file contributions + * @param userId - The user ID who contributed + * @param dlpId - The DLP ID + */ +export function updateDlpTotals(userId: string, dlpId: string): void { + // Create or load DLP user totals + const dlpUserTotalsId = getUserTotalsIdDlp(userId, dlpId); + const dlpUserTotals = getOrCreateUserTotals(dlpUserTotalsId); + dlpUserTotals.fileContributionsCount = + dlpUserTotals.fileContributionsCount.plus(GraphBigInt.fromI32(1)); + dlpUserTotals.save(); + + // Update DLP file contribution totals + const dlpTotalsId = getTotalsDlpId(dlpId); + const dlpTotals = getOrCreateTotals(dlpTotalsId); + dlpTotals.totalFileContributions = dlpTotals.totalFileContributions.plus( + GraphBigInt.fromI32(1), + ); + + // If this is the user's first contribution to this DLP, increment unique contributors + if (dlpUserTotals.fileContributionsCount.toI32() === 1) { + dlpTotals.uniqueFileContributors = dlpTotals.uniqueFileContributors.plus( + GraphBigInt.fromI32(1), + ); + } + + dlpTotals.save(); +} + +/** + * Updates both global and DLP totals for file contributions + * @param userId - The user ID who contributed + * @param dlpId - The DLP ID (optional, if not provided only global totals are updated) + */ +export function updateAllTotals( + userId: string, + dlpId: string | null = null, +): void { + updateGlobalTotals(userId); + + if (dlpId) { + updateDlpTotals(userId, dlpId); + } +} + +/** + * Updates totals based on file owner (used in V1 where we need to get user from file) + * @param fileId - The file ID to look up the owner + * @param dlpId - Optional DLP ID + */ +export function updateTotalsFromFile( + fileId: string, + dlpId: string | null = null, +): void { + const file = File.load(fileId); + if (!file || !file.owner) { + log.warning("Cannot update totals: file {} not found or has no owner", [ + fileId, + ]); + return; + } + + updateAllTotals(file.owner, dlpId); +} diff --git a/src/lib/contract/v1/data-registry.ts b/src/lib/contract/v1/data-registry.ts index 79d814c..53f3c2f 100644 --- a/src/lib/contract/v1/data-registry.ts +++ b/src/lib/contract/v1/data-registry.ts @@ -1,109 +1,56 @@ -import { BigInt as GraphBigInt, log } from "@graphprotocol/graph-ts"; - -import { - DataRegistryProof, - File, - FileOwner, -} from "../../../../generated/schema"; +import { log } from "@graphprotocol/graph-ts"; import { FileAdded as FileAddedEvent, ProofAdded as FileProofAdded, } from "../../../../generated/DataRegistryImplementationV1/DataRegistryImplementationV1"; -import { getEpochForBlock } from "../../entity/epoch"; // FIX: Added getEpochForBlock and EPOCH_REFERENCE_ID_CURRENT here +import { getEpochForBlock } from "../../entity/epoch"; import { - getOrCreateUserTotals, - getUserTotalsId, -} from "../../entity/usertotals"; -import { getOrCreateTotals, TOTALS_ID_GLOBAL } from "../../entity/totals"; -import { getOrCreateUser } from "../shared"; + createFileFromEvent, + logDataRegistryEvent, + createDataRegistryProof, + updateTotalsFromFile, + ERROR_NO_EPOCH, + DEFAULT_SCHEMA_ID, +} from "../shared/index"; export function handleFileAddedV1(event: FileAddedEvent): void { - log.info("Handling DataRegistry FileAdded with transaction hash: {}", [ - event.transaction.hash.toHex(), - ]); - - // Create user entity if it doesn't exist - const user = getOrCreateUser(event.params.ownerAddress.toHex()); - - // Create new File entity - const file = new File(event.params.fileId.toString()); - file.owner = user.id; - file.url = event.params.url; - file.addedAtBlock = event.block.number; - file.addedAtTimestamp = event.block.timestamp; - file.transactionHash = event.transaction.hash; - - // V1 of the contract does not support schemaId, so we set it to 0 - file.schemaId = GraphBigInt.fromI32(0); - - file.save(); - - const ownership = new FileOwner(event.params.fileId.toString()); - ownership.ownerAddress = event.params.ownerAddress; - ownership.save(); + logDataRegistryEvent("FileAdded", event.transaction.hash.toHex()); + + // Create file entity using shared utility + // V1 of the contract does not support schemaId, so we use default (0) + createFileFromEvent( + event.params.fileId.toString(), + event.params.ownerAddress.toHex(), + event.params.url, + event.block, + event.transaction, + DEFAULT_SCHEMA_ID, + ); } export function handleDataRegistryProofAddedV1(event: FileProofAdded): void { - log.info("Handling DataRegistry ProofAdded with transaction hash: {}", [ - event.transaction.hash.toHex(), - ]); + logDataRegistryEvent("ProofAdded", event.transaction.hash.toHex()); // Get epoch for the current block const epochId = getEpochForBlock(event.block.number); if (!epochId) { - log.error("No epoch found for block {}", [event.block.number.toString()]); + log.error(ERROR_NO_EPOCH + " {}", [event.block.number.toString()]); return; } - // Create a new DataRegistryProof entity - const proof = new DataRegistryProof(event.transaction.hash.toHex()); - - // Load File - const fileOwner = FileOwner.load(event.params.fileId.toString()); - if (fileOwner !== null) { - const userId = fileOwner.ownerAddress.toHex(); - proof.user = userId; - } else { - log.error("File ownership '{}' not found for data registry proof: {}", [ - event.params.fileId.toString(), - proof.id, - ]); - } - - // Populate fields based on the event data - proof.epoch = epochId; - proof.fileId = event.params.fileId; - proof.proofIndex = event.params.proofIndex; - proof.createdAt = event.block.timestamp; - proof.createdAtBlock = event.block.number; - proof.createdTxHash = event.transaction.hash; - - // Save the proof to the store - proof.save(); - - if (!fileOwner) { - return; - } - const userId = fileOwner.ownerAddress.toHex(); - - // Update user totals - const userTotalsId = getUserTotalsId(userId); - const userTotals = getOrCreateUserTotals(userTotalsId); - userTotals.fileContributionsCount = userTotals.fileContributionsCount.plus( - GraphBigInt.fromI32(1), + // Create proof using shared utility + // V1 doesn't have user or DLP associations in the proof + createDataRegistryProof( + event.transaction.hash.toHex(), + epochId, + event.params.fileId, + event.params.proofIndex, + event.block, + event.transaction, ); - userTotals.save(); - // Update global file contribution totals - const totals = getOrCreateTotals(TOTALS_ID_GLOBAL); - totals.totalFileContributions = totals.totalFileContributions.plus( - GraphBigInt.fromI32(1), - ); - if (userTotals.fileContributionsCount.toI32() === 1) { - totals.uniqueFileContributors = totals.uniqueFileContributors.plus( - GraphBigInt.fromI32(1), - ); - } - totals.save(); + // Update totals using shared utility + // V1 only has global totals, no DLP-specific totals + updateTotalsFromFile(event.params.fileId.toString()); } diff --git a/src/lib/contract/v2/data-registry.ts b/src/lib/contract/v2/data-registry.ts index bc846a5..6ccf962 100644 --- a/src/lib/contract/v2/data-registry.ts +++ b/src/lib/contract/v2/data-registry.ts @@ -1,147 +1,74 @@ -import { BigInt as GraphBigInt, log } from "@graphprotocol/graph-ts"; +import { log } from "@graphprotocol/graph-ts"; -import { - DataRegistryProof, - File, - FileOwner, - Dlp, -} from "../../../../generated/schema"; +import { Dlp, File } from "../../../../generated/schema"; import { FileAdded as FileAddedEvent, ProofAdded as FileProofAdded, } from "../../../../generated/DataRegistryImplementationV2/DataRegistryImplementationV2"; -import { - getOrCreateUserTotals, - getUserTotalsId, - getUserTotalsIdDlp, -} from "../../entity/usertotals"; -import { - getOrCreateTotals, - getTotalsIdDlp, - TOTALS_ID_GLOBAL, -} from "../../entity/totals"; import { getEpochForBlock } from "../../entity/epoch"; -import { getOrCreateUser } from "../shared"; +import { + createFileFromEvent, + logDataRegistryEvent, + createDataRegistryProof, + updateAllTotals, + ERROR_NO_EPOCH, + ERROR_DLP_NOT_FOUND, + DEFAULT_SCHEMA_ID, +} from "../shared/index"; export function handleFileAddedV2(event: FileAddedEvent): void { - log.info("Handling DataRegistry FileAdded with transaction hash: {}", [ - event.transaction.hash.toHex(), - ]); - - // Create user entity if it doesn't exist - const user = getOrCreateUser(event.params.ownerAddress.toHex()); - - // Create new File entity - const file = new File(event.params.fileId.toString()); - file.owner = user.id; - file.url = event.params.url; - file.addedAtBlock = event.block.number; - file.addedAtTimestamp = event.block.timestamp; - file.transactionHash = event.transaction.hash; - - // V2 of the contract does not support schemaId, so we set it to 0 - file.schemaId = GraphBigInt.fromI32(0); - - file.save(); - - const ownership = new FileOwner(event.params.fileId.toString()); - ownership.ownerAddress = event.params.ownerAddress; - ownership.save(); + logDataRegistryEvent("FileAdded", event.transaction.hash.toHex()); + + // Create file entity using shared utility + // V2 of the contract does not support schemaId, so we use default (0) + createFileFromEvent( + event.params.fileId.toString(), + event.params.ownerAddress.toHex(), + event.params.url, + event.block, + event.transaction, + DEFAULT_SCHEMA_ID, + ); } export function handleDataRegistryProofAddedV2(event: FileProofAdded): void { - log.info("Handling DataRegistry ProofAdded with transaction hash: {}", [ - event.transaction.hash.toHex(), - ]); + logDataRegistryEvent("ProofAdded", event.transaction.hash.toHex()); // Get epoch for the current block const epochId = getEpochForBlock(event.block.number); - // FIX: Check for "-1" explicitly, as it is a truthy string + // Check for "-1" explicitly, as it is a truthy string if (epochId == "-1") { - log.error("No epoch found for block {}", [event.block.number.toString()]); + log.error(ERROR_NO_EPOCH + " {}", [event.block.number.toString()]); return; } - // FIX: Load DLP instead of creating it to handle non-existent DLP case gracefully + // Load DLP instead of creating it to handle non-existent DLP case gracefully const dlp = Dlp.load(event.params.dlpId.toString()); if (dlp == null) { - log.error("DLP not found for proof: {}", [event.params.dlpId.toString()]); + log.error(ERROR_DLP_NOT_FOUND + ": {}", [event.params.dlpId.toString()]); return; } - // Create a new DataRegistryProof entity - const proof = new DataRegistryProof(event.transaction.hash.toHex()); - - // Load File - const fileOwner = FileOwner.load(event.params.fileId.toString()); - if (fileOwner !== null) { - const userId = fileOwner.ownerAddress.toHex(); - proof.user = userId; - } else { - log.warning( - "File '{}' not found for data registry proof (could not set user id): {}", - [event.params.fileId.toString(), proof.id], - ); - } - - // Populate fields based on the event data - proof.dlp = dlp.id; - proof.epoch = epochId; - proof.fileId = event.params.fileId; - proof.proofIndex = event.params.proofIndex; - proof.createdAt = event.block.timestamp; - proof.createdAtBlock = event.block.number; - proof.createdTxHash = event.transaction.hash; - - // Save the proof to the store - proof.save(); - - if (!fileOwner) { - return; - } - const userId = fileOwner.ownerAddress.toHex(); - - // Update user totals - const userTotalsId = getUserTotalsId(userId); - const userTotals = getOrCreateUserTotals(userTotalsId); - userTotals.fileContributionsCount = userTotals.fileContributionsCount.plus( - GraphBigInt.fromI32(1), + // Create proof using shared utility + // V2 has DLP association but no user association in the proof + createDataRegistryProof( + event.transaction.hash.toHex(), + epochId, + event.params.fileId, + event.params.proofIndex, + event.block, + event.transaction, + null, // no userId in V2 proof + dlp.id, ); - userTotals.save(); - // Update global unique file contribution totals - const totals = getOrCreateTotals(TOTALS_ID_GLOBAL); - totals.totalFileContributions = totals.totalFileContributions.plus( - GraphBigInt.fromI32(1), - ); - if (userTotals.fileContributionsCount.toI32() === 1) { - totals.uniqueFileContributors = totals.uniqueFileContributors.plus( - GraphBigInt.fromI32(1), - ); + // Update totals using shared utility + // V2 has both global and DLP totals + const file = File.load(event.params.fileId.toString()); + if (!file || !file.owner) { + return; } - totals.save(); - - // Create or load dlp user totals - const dlpUserTotalsId = getUserTotalsIdDlp( - userId, - event.params.dlpId.toString(), - ); - const dlpUserTotals = getOrCreateUserTotals(dlpUserTotalsId); - dlpUserTotals.fileContributionsCount = - dlpUserTotals.fileContributionsCount.plus(GraphBigInt.fromI32(1)); - dlpUserTotals.save(); - // Update dlp file contribution totals - const dlpTotalsId = getTotalsIdDlp(event.params.dlpId.toString()); - const dlpTotals = getOrCreateTotals(dlpTotalsId); - dlpTotals.totalFileContributions = dlpTotals.totalFileContributions.plus( - GraphBigInt.fromI32(1), - ); - if (dlpUserTotals.fileContributionsCount.toI32() === 1) { - dlpTotals.uniqueFileContributors = dlpTotals.uniqueFileContributors.plus( - GraphBigInt.fromI32(1), - ); - } - dlpTotals.save(); + updateAllTotals(file.owner, event.params.dlpId.toString()); } diff --git a/src/lib/contract/v3/data-registry.ts b/src/lib/contract/v3/data-registry.ts index b093cb6..0202080 100644 --- a/src/lib/contract/v3/data-registry.ts +++ b/src/lib/contract/v3/data-registry.ts @@ -1,136 +1,130 @@ import { BigInt as GraphBigInt, log } from "@graphprotocol/graph-ts"; -import { - DataRegistryProof, - Dlp, - File, - FileOwner, -} from "../../../../generated/schema"; +import { Epoch, PerformanceDlpEpochUser } from "../../../../generated/schema"; import { FileAdded as FileAddedEvent, ProofAdded as FileProofAdded, } from "../../../../generated/DataRegistryImplementationV3/DataRegistryImplementationV3"; -import { - getOrCreateUserTotals, - getUserTotalsId, - getUserTotalsIdDlp, -} from "../../entity/usertotals"; -import { - getOrCreateTotals, - getTotalsIdDlp, - TOTALS_ID_GLOBAL, -} from "../../entity/totals"; -import { getOrCreateUser } from "../shared"; +import { getOrCreateTotalsForDlpEpochPerformance } from "../../entity/totals"; import { getEpochForBlock } from "../../entity/epoch"; +import { getDlpEpochUserId } from "../../entity/dlpEpochUser"; +import { + getOrCreateDlp, + getOrCreateUser, + createFileFromEvent, + logDataRegistryEvent, + createDataRegistryProof, + updateAllTotals, + ERROR_NO_EPOCH, + DEFAULT_SCHEMA_ID, + ONE, +} from "../shared/index"; export function handleFileAddedV3(event: FileAddedEvent): void { - log.info("Handling DataRegistry FileAdded with transaction hash: {}", [ - event.transaction.hash.toHex(), - ]); + logDataRegistryEvent("FileAdded", event.transaction.hash.toHex()); + + // Create file entity using shared utility + // V3 of the contract does not support schemaId, so we use default (0) + createFileFromEvent( + event.params.fileId.toString(), + event.params.ownerAddress.toHex(), + event.params.url, + event.block, + event.transaction, + DEFAULT_SCHEMA_ID, + ); +} - // Create user entity if it doesn't exist - const user = getOrCreateUser(event.params.ownerAddress.toHex()); +export function handleDataRegistryProofAddedV3(event: FileProofAdded): void { + logDataRegistryEvent("ProofAdded", event.transaction.hash.toHex()); - // Create new File entity - const file = new File(event.params.fileId.toString()); - file.owner = user.id; - file.url = event.params.url; - file.addedAtBlock = event.block.number; - file.addedAtTimestamp = event.block.timestamp; - file.transactionHash = event.transaction.hash; + const epochId = getEpochForBlock(event.block.number); + // Check for "-1" explicitly, as it is a truthy string + if (epochId == "-1") { + log.error(ERROR_NO_EPOCH + " {}", [event.block.number.toString()]); + return; + } - // V3 of the contract does not support schemaId, so we set it to 0 - file.schemaId = GraphBigInt.fromI32(0); + const userId = event.params.ownerAddress.toHex(); + const dlpId = event.params.dlpId.toString(); - file.save(); + const dlp = getOrCreateDlp(dlpId); + getOrCreateUser(userId); + + // Create proof using shared utility + // V3 has both user and DLP associations in the proof + createDataRegistryProof( + event.transaction.hash.toHex(), + epochId, + event.params.fileId, + event.params.proofIndex, + event.block, + event.transaction, + userId, + dlp.id, + ); - const ownership = new FileOwner(event.params.fileId.toString()); - ownership.ownerAddress = event.params.ownerAddress; - ownership.save(); + // Update totals using shared utility + updateAllTotals(userId, dlpId); + + // Update DLP epoch user (V3 specific functionality) + updateDlpEpochUser(event, epochId, userId, dlpId); } -export function handleDataRegistryProofAddedV3(event: FileProofAdded): void { - log.info("Handling DataRegistry ProofAdded with transaction hash: {}", [ - event.transaction.hash.toHex(), - ]); +// Removed: now using shared createDataRegistryProof function - // Get epoch for the current block - const epochId = getEpochForBlock(event.block.number); - // Check for "-1" explicitly, as it is a truthy string - if (epochId == "-1") { - log.error("No epoch found for block {}", [event.block.number.toString()]); +// Removed: now using shared updateAllTotals function + +function updateDlpEpochUser( + event: FileProofAdded, + epochId: string, + userId: string, + dlpId: string, +): void { + const epoch = Epoch.load(epochId); + const dlp = getOrCreateDlp(dlpId); + if (!epoch) { + log.error("No epoch found for ID {}", [epochId]); return; } - // Load DLP instead of creating it to handle non-existent DLP case gracefully - const dlp = Dlp.load(event.params.dlpId.toString()); - if (dlp == null) { - log.error("DLP not found for proof: {}", [event.params.dlpId.toString()]); + if (!dlp.verificationBlockNumber) { return; } - // Create a new DataRegistryProof entity - const proof = new DataRegistryProof(event.transaction.hash.toHex()); + const verificationBlock = dlp.verificationBlockNumber!; - // Load File - const fileId = event.params.fileId; - const userId = event.params.ownerAddress.toHex(); + const eligibilityStartBlock = epoch.startBlock.gt(verificationBlock) + ? epoch.startBlock + : verificationBlock; - // Ensure the User entity exists - getOrCreateUser(userId); + if (!event.block.number.ge(eligibilityStartBlock)) { + return; + } - // Store proof based on the event data - proof.user = userId; - proof.dlp = dlp.id; - proof.epoch = epochId; - proof.fileId = fileId; - proof.proofIndex = event.params.proofIndex; - proof.createdAt = event.block.timestamp; - proof.createdAtBlock = event.block.number; - proof.createdTxHash = event.transaction.hash; - proof.save(); - - // Update user totals - const userTotalsId = getUserTotalsId(userId); - const userTotals = getOrCreateUserTotals(userTotalsId); - userTotals.fileContributionsCount = userTotals.fileContributionsCount.plus( - GraphBigInt.fromI32(1), - ); - userTotals.save(); + const id = getDlpEpochUserId(dlpId, epochId, userId); + let dlpEpochUser = PerformanceDlpEpochUser.load(id); - // Update global unique file contribution totals - const totals = getOrCreateTotals(TOTALS_ID_GLOBAL); - totals.totalFileContributions = totals.totalFileContributions.plus( - GraphBigInt.fromI32(1), - ); - if (userTotals.fileContributionsCount.toI32() === 1) { - totals.uniqueFileContributors = totals.uniqueFileContributors.plus( - GraphBigInt.fromI32(1), - ); + let firstContributionInEpoch = false; + if (dlpEpochUser == null) { + firstContributionInEpoch = true; + + dlpEpochUser = new PerformanceDlpEpochUser(id); + dlpEpochUser.save(); } - totals.save(); - // Create or load dlp user totals - const dlpUserTotalsId = getUserTotalsIdDlp( - userId, - event.params.dlpId.toString(), - ); - const dlpUserTotals = getOrCreateUserTotals(dlpUserTotalsId); - dlpUserTotals.fileContributionsCount = - dlpUserTotals.fileContributionsCount.plus(GraphBigInt.fromI32(1)); - dlpUserTotals.save(); - - // Update dlp file contribution totals - const dlpTotalsId = getTotalsIdDlp(event.params.dlpId.toString()); - const dlpTotals = getOrCreateTotals(dlpTotalsId); - dlpTotals.totalFileContributions = dlpTotals.totalFileContributions.plus( - GraphBigInt.fromI32(1), + const dlpEpochTotals = getOrCreateTotalsForDlpEpochPerformance( + dlpId, + epochId, ); - if (dlpUserTotals.fileContributionsCount.toI32() === 1) { - dlpTotals.uniqueFileContributors = dlpTotals.uniqueFileContributors.plus( - GraphBigInt.fromI32(1), - ); + dlpEpochTotals.totalFileContributions = + dlpEpochTotals.totalFileContributions.plus(ONE); + + if (firstContributionInEpoch) { + dlpEpochTotals.uniqueFileContributors = + dlpEpochTotals.uniqueFileContributors.plus(ONE); } - dlpTotals.save(); + + dlpEpochTotals.save(); } diff --git a/src/lib/contract/v4/query-engine.ts b/src/lib/contract/v4/query-engine.ts index 60756b1..bbc9e17 100644 --- a/src/lib/contract/v4/query-engine.ts +++ b/src/lib/contract/v4/query-engine.ts @@ -1,6 +1,12 @@ import { log } from "@graphprotocol/graph-ts"; import { PaymentReceived, Refiner } from "../../../../generated/schema"; import { PaymentReceived as PaymentReceivedEvent } from "../../../../generated/QueryEngineImplementation/QueryEngineImplementation"; +import { + getOrCreateTotals, + getOrCreateTotalsGlobal, + getTotalsDlpId, +} from "../../entity/totals"; +import { getTokenAmountInVana } from "../shared"; export function handlePaymentReceived(event: PaymentReceivedEvent): void { // Create unique ID from transaction hash and log index @@ -29,4 +35,21 @@ export function handlePaymentReceived(event: PaymentReceivedEvent): void { // Save the entity payment.save(); + + const amountInVana = getTokenAmountInVana( + event.params.token, + event.params.amount, + ); + + //save totals + // Update global unique file contribution totals + const totals = getOrCreateTotalsGlobal(); + totals.dataAccessFees = totals.dataAccessFees.plus(amountInVana); + totals.save(); + + // Update dlp file contribution totals + const dlpTotalsId = getTotalsDlpId(refiner.dlp); + const dlpTotals = getOrCreateTotals(dlpTotalsId); + dlpTotals.dataAccessFees = dlpTotals.dataAccessFees.plus(amountInVana); + dlpTotals.save(); } diff --git a/src/lib/contract/v5/data-permission.ts b/src/lib/contract/v5/data-permission.ts index 70af0d3..85ec742 100644 --- a/src/lib/contract/v5/data-permission.ts +++ b/src/lib/contract/v5/data-permission.ts @@ -11,7 +11,7 @@ import { ServerUntrusted, DataPermissionImplementation, } from "../../../../generated/DataPermissionImplementation/DataPermissionImplementation"; -import { Permission, TrustedServer } from "../../../../generated/schema"; +import { Permission, Server } from "../../../../generated/schema"; import { getOrCreateUser } from "../shared"; export function handlePermissionAdded(event: PermissionAdded): void { @@ -65,9 +65,10 @@ export function handlePermissionRevoked(event: PermissionRevoked): void { permission.isActive = false; permission.save(); } else { - log.warning("Received revoke event for a permission not found in subgraph: {}", [ - permissionId, - ]); + log.warning( + "Received revoke event for a permission not found in subgraph: {}", + [permissionId], + ); } } @@ -81,16 +82,16 @@ export function handleServerTrusted(event: ServerTrusted): void { const serverId = event.params.serverId; const compositeId = `${user.id}-${serverId.toHex()}`; - let trustedServer = TrustedServer.load(compositeId); - if (trustedServer == null) { - trustedServer = new TrustedServer(compositeId); - trustedServer.user = user.id; - trustedServer.serverAddress = serverId; + let server = Server.load(compositeId); + if (server == null) { + server = new Server(compositeId); + server.user = user.id; + server.serverAddress = serverId; } - trustedServer.serverUrl = event.params.serverUrl; - trustedServer.trustedAt = event.block.timestamp; - trustedServer.save(); + server.serverUrl = event.params.serverUrl; + server.trustedAt = event.block.timestamp; + server.save(); } export function handleServerUntrusted(event: ServerUntrusted): void { @@ -103,9 +104,9 @@ export function handleServerUntrusted(event: ServerUntrusted): void { const serverId = event.params.serverId.toHex(); const compositeId = `${userId}-${serverId}`; - const trustedServer = TrustedServer.load(compositeId); - if (trustedServer != null) { - store.remove("TrustedServer", compositeId); + const server = Server.load(compositeId); + if (server != null) { + store.remove("Server", compositeId); } else { log.warning("Attempted to untrust a server that was not found: {}", [ compositeId, diff --git a/src/lib/contract/v5/data-refiner-registry.ts b/src/lib/contract/v5/data-refiner-registry.ts deleted file mode 100644 index f46c93b..0000000 --- a/src/lib/contract/v5/data-refiner-registry.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { log } from "@graphprotocol/graph-ts"; -import { Refiner } from "../../../../generated/schema"; -import { RefinerAdded } from "../../../../generated/DataRefinerRegistryImplementation/DataRefinerRegistryImplementation"; - -export function handleRefinerAdded(event: RefinerAdded): void { - log.info("Handling RefinerAdded with transaction hash: {}", [ - event.transaction.hash.toHexString(), - ]); - - // Create new Refiner entity - const refiner = new Refiner(event.params.refinerId.toString()); - refiner.dlp = event.params.dlpId.toString(); - refiner.owner = event.transaction.from; - refiner.name = event.params.name; - refiner.schemaDefinitionUrl = event.params.schemaDefinitionUrl; - refiner.refinementInstructionUrl = event.params.refinementInstructionUrl; - - // Save the entity - refiner.save(); -} diff --git a/src/lib/contract/v5/dlp-registry.ts b/src/lib/contract/v5/dlp-registry.ts index 98c2261..cc532a8 100644 --- a/src/lib/contract/v5/dlp-registry.ts +++ b/src/lib/contract/v5/dlp-registry.ts @@ -3,9 +3,8 @@ import { DlpRegistered, DlpUpdated, DlpStatusUpdated, - DlpVerificationUpdated, + DlpVerificationBlockUpdated, DlpTokenUpdated, - DlpRegistrationDepositAmountUpdated, } from "../../../../generated/DLPRegistryImplementationV5/DLPRegistryImplementationV5"; import { Dlp } from "../../../../generated/schema"; @@ -46,9 +45,6 @@ export function handleDlpRegisteredV5(event: DlpRegistered): void { dlp.createdAtBlock = event.block.number; dlp.status = GraphBigInt.fromI32(dlpStatus.REGISTERED); - // New field in v5 - dlp.isVerified = false; - // Keep staking fields for backward compatibility but set to zero dlp.performanceRating = GraphBigInt.zero(); @@ -102,25 +98,16 @@ export function handleDlpStatusUpdatedV5(event: DlpStatusUpdated): void { const newStatus = event.params.newStatus; dlp.status = GraphBigInt.fromI32(newStatus); - // Track eligibility transitions - if (newStatus === dlpStatus.ELIGIBLE) { - dlp.isRewardEligible = true; - dlp.rewardEligibleAt = event.block.timestamp; - dlp.rewardEligibleAtBlock = event.block.number; - } else { - dlp.isRewardEligible = false; - } - dlp.save(); } else { log.error("DLP not found during status update: {}", [dlpId]); } } -export function handleDlpVerificationUpdatedV5( - event: DlpVerificationUpdated, +export function handleDlpVerificationBlockUpdatedV5( + event: DlpVerificationBlockUpdated, ): void { - log.info("Handling DlpVerificationUpdated with transaction hash: {}", [ + log.info("Handling DlpVerificationBlockUpdated with transaction hash: {}", [ event.transaction.hash.toHexString(), ]); @@ -128,22 +115,7 @@ export function handleDlpVerificationUpdatedV5( const dlp = Dlp.load(dlpId); if (dlp != null) { - dlp.isVerified = event.params.verified; - dlp.save(); - - // Update status based on verification and token status - let isEligible = false; - if (dlp.isVerified) { - if (!(dlp.token === null)) { - isEligible = true; - } - } - - if (isEligible) { - dlp.status = GraphBigInt.fromI32(dlpStatus.ELIGIBLE); - } else { - dlp.status = GraphBigInt.fromI32(dlpStatus.REGISTERED); - } + dlp.verificationBlockNumber = event.params.verificationBlockNumber; dlp.save(); } else { log.error("DLP not found during verification update: {}", [dlpId]); @@ -167,27 +139,4 @@ export function handleDlpTokenUpdatedV5(event: DlpTokenUpdated): void { dlp.token = event.params.tokenAddress; dlp.save(); - - // Update status based on verification and token status - let isEligible = false; - if (dlp.isVerified) { - if (!(dlp.token === null)) { - isEligible = true; - } - } - - if (isEligible) { - dlp.status = GraphBigInt.fromI32(dlpStatus.ELIGIBLE); - } else { - dlp.status = GraphBigInt.fromI32(dlpStatus.REGISTERED); - } - dlp.save(); -} - -export function handleDlpRegistrationDepositAmountUpdatedV5( - event: DlpRegistrationDepositAmountUpdated, -): void { - log.info("handleDlpRegistrationDepositAmountUpdatedV5: {}", [ - event.transaction.hash.toHexString(), - ]); } diff --git a/src/lib/contract/v5/query-engine.ts b/src/lib/contract/v5/query-engine.ts deleted file mode 100644 index 915cdb2..0000000 --- a/src/lib/contract/v5/query-engine.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { log } from "@graphprotocol/graph-ts"; -import { Refiner, PaymentReceived } from "../../../../generated/schema"; -import { PaymentReceived as PaymentReceivedEvent } from "../../../../generated/QueryEngineImplementation/QueryEngineImplementation"; - -export function handlePaymentReceived(event: PaymentReceivedEvent): void { - log.info("Handling PaymentReceived for refiner: {}", [ - event.params.refinerId.toString(), - ]); - - // Create a unique ID for this payment - const paymentId = `${event.transaction.hash.toHexString()}-${event.logIndex.toString()}`; - - // Load the associated refiner - const refiner = Refiner.load(event.params.refinerId.toString()); - - if (refiner) { - // Create payment entity - const payment = new PaymentReceived(paymentId); - payment.refiner = refiner.id; - payment.token = event.params.token; - payment.amount = event.params.amount; - payment.jobId = event.params.jobId; - payment.receivedAt = event.block.timestamp; - payment.receivedAtBlock = event.block.number; - payment.receivedTxHash = event.transaction.hash; - payment.save(); - } else { - log.error("Payment received for unknown refiner: {}", [ - event.params.refinerId.toString(), - ]); - } -} diff --git a/src/lib/entity/bootstrap/bootstrap.ts b/src/lib/entity/bootstrap/bootstrap.ts new file mode 100644 index 0000000..94545c1 --- /dev/null +++ b/src/lib/entity/bootstrap/bootstrap.ts @@ -0,0 +1,14 @@ +import { BigInt, ethereum } from "@graphprotocol/graph-ts"; +import { dlps } from "../../../mapping"; +import { getOrCreateDlp } from "../../contract/shared"; + +export function handleBootstrap(block: ethereum.Block): void { + for (let i = 0; i < dlps.length; i++) { + const dlp = getOrCreateDlp(dlps[i].id.toString()); + dlp.verificationBlockNumber = BigInt.fromI32( + dlps[i].verificationBlockNumber, + ); + + dlp.save(); + } +} diff --git a/src/lib/entity/dlpEpochUser/constants.ts b/src/lib/entity/dlpEpochUser/constants.ts new file mode 100644 index 0000000..81343d6 --- /dev/null +++ b/src/lib/entity/dlpEpochUser/constants.ts @@ -0,0 +1,7 @@ +export function getDlpEpochUserId( + dlpId: string, + epochId: string, + userId: string, +): string { + return `dlp-${dlpId}-epoch-${epochId}-user-${userId}`; +} diff --git a/src/lib/entity/dlpEpochUser/dlp-epoch-user.ts b/src/lib/entity/dlpEpochUser/dlp-epoch-user.ts new file mode 100644 index 0000000..5cb5c00 --- /dev/null +++ b/src/lib/entity/dlpEpochUser/dlp-epoch-user.ts @@ -0,0 +1,17 @@ +import { BigInt as GraphBigInt } from "@graphprotocol/graph-ts"; +import { getDlpEpochUserId } from "./constants"; +import { PerformanceDlpEpochUser } from "../../../../generated/schema"; + +export function getOrCreateDlpEpochUser( + dlpId: string, + epochId: string, + userId: string, +): PerformanceDlpEpochUser { + const id = getDlpEpochUserId(dlpId, epochId, userId); + let dlpEpochUser = PerformanceDlpEpochUser.load(id); + if (dlpEpochUser == null) { + dlpEpochUser = new PerformanceDlpEpochUser(id); + dlpEpochUser.save(); + } + return dlpEpochUser; +} diff --git a/src/lib/entity/dlpEpochUser/index.ts b/src/lib/entity/dlpEpochUser/index.ts new file mode 100644 index 0000000..f971e9c --- /dev/null +++ b/src/lib/entity/dlpEpochUser/index.ts @@ -0,0 +1,2 @@ +export * from "./constants"; +export * from "./dlp-epoch-user"; diff --git a/src/lib/entity/totals/constants.ts b/src/lib/entity/totals/constants.ts index 57db95f..b9bbf69 100644 --- a/src/lib/entity/totals/constants.ts +++ b/src/lib/entity/totals/constants.ts @@ -1,5 +1,12 @@ export const TOTALS_ID_GLOBAL = "global"; -export function getTotalsIdDlp(dlpId: string): string { +export function getTotalsDlpId(dlpId: string): string { return `dlp-${dlpId}`; } + +export function getTotalsDlpEpochPerformanceId( + dlpId: string, + epochId: string, +): string { + return `performance-dlp-${dlpId}-epoch-${epochId}`; +} diff --git a/src/lib/entity/totals/totals.ts b/src/lib/entity/totals/totals.ts index 6e20d48..6244d21 100644 --- a/src/lib/entity/totals/totals.ts +++ b/src/lib/entity/totals/totals.ts @@ -1,15 +1,18 @@ import { BigInt as GraphBigInt } from "@graphprotocol/graph-ts"; +import { BigDecimal as GraphBigDecimal } from "@graphprotocol/graph-ts"; import { Totals } from "../../../../generated/schema"; -import { getTotalsIdDlp, TOTALS_ID_GLOBAL } from "./constants"; +import { getTotalsDlpEpochPerformanceId, TOTALS_ID_GLOBAL } from "./constants"; export function getOrCreateTotalsGlobal(): Totals { - const totalsId = TOTALS_ID_GLOBAL; - return getOrCreateTotals(totalsId); + return getOrCreateTotals(TOTALS_ID_GLOBAL); } -export function getOrCreateTotalsForDlp(dlpId: string): Totals { - const totalsId = getTotalsIdDlp(dlpId); +export function getOrCreateTotalsForDlpEpochPerformance( + dlpId: string, + epochId: string, +): Totals { + const totalsId = getTotalsDlpEpochPerformanceId(dlpId, epochId); return getOrCreateTotals(totalsId); } @@ -19,6 +22,7 @@ export function getOrCreateTotals(id: string): Totals { totals = new Totals(id); totals.totalFileContributions = GraphBigInt.zero(); totals.uniqueFileContributors = GraphBigInt.zero(); + totals.dataAccessFees = GraphBigDecimal.zero(); totals.save(); } return totals; diff --git a/src/mapping.ts.template b/src/mapping.ts.template index ed2dfbc..4c5f599 100644 --- a/src/mapping.ts.template +++ b/src/mapping.ts.template @@ -24,12 +24,28 @@ export class EpochRange { } } +export class Dlp { + id: i32; + verificationBlockNumber: i32; + + constructor(id: i32, verificationBlockNumber: i32) { + this.id = id; + this.verificationBlockNumber = verificationBlockNumber; + } +} + export const epochRanges: EpochRange[] = [ {{#epochRanges}} new EpochRange({{ startBlock }}, {{ endBlock }}), {{/epochRanges}} ]; +export const dlps: Dlp[] = [ + {{#dlps}} + new Dlp({{ id }}, {{ verificationBlockNumber }}), + {{/dlps}} +]; + // V1 {{#includes.v1.dataRegistry}} export * from "./lib/contract/v1/data-registry"; @@ -65,4 +81,10 @@ export * from "./lib/contract/v5/dlp-performance"; {{/includes.v5.dlpPerformance}} {{#includes.v5.dataPermission}} export * from "./lib/contract/v5/data-permission"; -{{/includes.v5.dataPermission}} \ No newline at end of file +{{/includes.v5.dataPermission}} + +//uniswap +{{#includes.uniswap.v3}} +export * from "./uniswap/v3/mappings/factory"; +export * from "./uniswap/v3/mappings/core"; +{{/includes.uniswap.v3}} \ No newline at end of file diff --git a/src/uniswap/common/backfill.ts b/src/uniswap/common/backfill.ts new file mode 100644 index 0000000..fabf604 --- /dev/null +++ b/src/uniswap/common/backfill.ts @@ -0,0 +1,125 @@ +import { Address, BigInt, ethereum } from '@graphprotocol/graph-ts' + +import { ERC20 } from '../../../generated/Factory/ERC20' +import { Pool as PoolABI } from '../../../generated/Factory/Pool' +import { Pool, Token } from '../../../generated/schema' +import { Pool as PoolTemplate } from '../../../generated/templates' +import { ZERO_BD, ZERO_BI } from './constants' +import { fetchTokenDecimals, fetchTokenName, fetchTokenSymbol, fetchTokenTotalSupply } from './token' +import { convertTokenToDecimal } from './utils' + +function populateToken(tokenAddress: Address): void { + let token = Token.load(tokenAddress) + if (token != null) { + return + } + token = new Token(tokenAddress) + token.symbol = fetchTokenSymbol(tokenAddress) + token.name = fetchTokenName(tokenAddress) + token.totalSupply = fetchTokenTotalSupply(tokenAddress) + const decimals = fetchTokenDecimals(tokenAddress) + if (decimals === null) { + return + } + token.decimals = decimals + token.derivedETH = ZERO_BD + token.volume = ZERO_BD + token.volumeUSD = ZERO_BD + token.feesUSD = ZERO_BD + token.untrackedVolumeUSD = ZERO_BD + token.totalValueLocked = ZERO_BD + token.totalValueLockedUSD = ZERO_BD + token.totalValueLockedUSDUntracked = ZERO_BD + token.txCount = ZERO_BI + token.poolCount = ZERO_BI + token.whitelistPools = [] + token.save() +} + +/** + * Create entries in store for hard-coded pools and tokens. This is only + * used for generating optimism pre-regenesis data. + */ +export function populateEmptyPools( + event: ethereum.Event, + poolMappings: Array, + whitelistTokens: string[] +): void { + const length = poolMappings.length + for (let i = 0; i < length; ++i) { + const poolMapping = poolMappings[i] + const newAddress = poolMapping[1] + const token0Address = poolMapping[2] + const token1Address = poolMapping[3] + + const poolContract = PoolABI.bind(newAddress) + const pool = new Pool(newAddress) as Pool + pool.createdAtBlockNumber = event.block.number + pool.createdAtTimestamp = event.block.timestamp + pool.token0 = token0Address + pool.token1 = token1Address + pool.liquidity = poolContract.liquidity() + pool.sqrtPrice = ZERO_BI + pool.token0Price = ZERO_BD + pool.token1Price = ZERO_BD + pool.observationIndex = ZERO_BI + pool.liquidityProviderCount = ZERO_BI + pool.txCount = ZERO_BI + pool.totalValueLockedToken0 = ZERO_BD + pool.totalValueLockedToken1 = ZERO_BD + pool.totalValueLockedETH = ZERO_BD + pool.totalValueLockedUSD = ZERO_BD + pool.totalValueLockedUSDUntracked = ZERO_BD + pool.volumeToken0 = ZERO_BD + pool.volumeToken1 = ZERO_BD + pool.volumeUSD = ZERO_BD + pool.untrackedVolumeUSD = ZERO_BD + pool.feesUSD = ZERO_BD + pool.collectedFeesToken0 = ZERO_BD + pool.collectedFeesToken1 = ZERO_BD + pool.collectedFeesUSD = ZERO_BD + + // need fee tier + const feeTier = poolContract.fee() + pool.feeTier = BigInt.fromI32(feeTier) + + // create token entities if needed + populateToken(token0Address) + populateToken(token1Address) + const token0 = Token.load(token0Address) + const token1 = Token.load(token1Address) + + if (token0 && token1) { + if (whitelistTokens.includes(pool.token0.toHexString())) { + const newPools = token1.whitelistPools + newPools.push(pool.id) + token1.whitelistPools = newPools + } + + if (whitelistTokens.includes(token1.id.toHexString())) { + const newPools = token0.whitelistPools + newPools.push(pool.id) + token0.whitelistPools = newPools + } + + // populate the TVL by call contract balanceOf + const token0Contract = ERC20.bind(Address.fromBytes(pool.token0)) + const tvlToken0Raw = token0Contract.balanceOf(Address.fromBytes(pool.id)) + const tvlToken0Adjusted = convertTokenToDecimal(tvlToken0Raw, token0.decimals) + pool.totalValueLockedToken0 = tvlToken0Adjusted + token0.totalValueLocked = tvlToken0Adjusted + + const token1Contract = ERC20.bind(Address.fromBytes(pool.token1)) + const tvlToken1Raw = token1Contract.balanceOf(Address.fromBytes(pool.id)) + const tvlToken1Adjusted = convertTokenToDecimal(tvlToken1Raw, token1.decimals) + pool.totalValueLockedToken1 = tvlToken1Adjusted + token1.totalValueLocked = tvlToken1Adjusted + + // add pool to tracked address and store entities + PoolTemplate.create(Address.fromBytes(pool.id)) + token0.save() + token1.save() + pool.save() + } + } +} diff --git a/src/uniswap/common/constants.ts b/src/uniswap/common/constants.ts new file mode 100644 index 0000000..e8b11f9 --- /dev/null +++ b/src/uniswap/common/constants.ts @@ -0,0 +1,14 @@ +import { Address, BigDecimal, BigInt } from '@graphprotocol/graph-ts' + +import { Factory as FactoryContract } from '../../../generated/Factory/Factory' +import { FACTORY_ADDRESS } from './chain' + +export const ADDRESS_ZERO = '0x0000000000000000000000000000000000000000' + +export const ZERO_BI = BigInt.fromI32(0) +export const ONE_BI = BigInt.fromI32(1) +export const ZERO_BD = BigDecimal.fromString('0') +export const ONE_BD = BigDecimal.fromString('1') +export const BI_18 = BigInt.fromI32(18) + +export const factoryContract = FactoryContract.bind(Address.fromString(FACTORY_ADDRESS)) diff --git a/src/uniswap/common/entityGetters.ts b/src/uniswap/common/entityGetters.ts new file mode 100644 index 0000000..f90eb5f --- /dev/null +++ b/src/uniswap/common/entityGetters.ts @@ -0,0 +1,54 @@ +import { Address, Bytes } from '@graphprotocol/graph-ts' + +import { Bundle, Factory, Pool, Token } from '../../../generated/schema' +import { FACTORY_ADDRESS } from './chain' +import { ADDRESS_ZERO, ZERO_BD, ZERO_BI } from './constants' + +export function getBundle(): Bundle { + let bundle = Bundle.load('1') + + if (!bundle) { + bundle = new Bundle('1') + bundle.ethPriceUSD = ZERO_BD + bundle.save() + } + + return bundle +} + +export function getFactory(): Factory { + let factory = Factory.load(Address.fromString(FACTORY_ADDRESS)) + if (!factory) { + factory = new Factory(Address.fromString(FACTORY_ADDRESS)) + factory.poolCount = ZERO_BI + factory.totalVolumeETH = ZERO_BD + factory.totalVolumeUSD = ZERO_BD + factory.untrackedVolumeUSD = ZERO_BD + factory.totalFeesUSD = ZERO_BD + factory.totalFeesETH = ZERO_BD + factory.totalValueLockedETH = ZERO_BD + factory.totalValueLockedUSD = ZERO_BD + factory.totalValueLockedUSDUntracked = ZERO_BD + factory.totalValueLockedETHUntracked = ZERO_BD + factory.txCount = ZERO_BI + factory.owner = ADDRESS_ZERO + + getBundle() + } + + return factory +} + +// Function should only be called from core when pools are gaurenteed (they are created in factory) +export function getPool(address: Bytes): Pool { + const pool = Pool.load(address)! + + return pool +} + +// Function should only be called from core when tokens are gaurenteed (they are created in factory) +export function getToken(address: Bytes): Token { + const token = Token.load(address)! + + return token +} diff --git a/src/uniswap/common/position.ts b/src/uniswap/common/position.ts new file mode 100644 index 0000000..d78f804 --- /dev/null +++ b/src/uniswap/common/position.ts @@ -0,0 +1,18 @@ +import { BigInt } from '@graphprotocol/graph-ts' + +export function hexToBigint(hex: string): BigInt { + let bigint = BigInt.fromI32(0) + let power = BigInt.fromI32(1) + for (let i = hex.length - 1; i >= 0; i--) { + const char = hex.charCodeAt(i) + let value = 0 + if (char >= 48 && char <= 57) { + value = char - 48 + } else if (char >= 65 && char <= 70) { + value = char - 55 + } + bigint = bigint.plus(BigInt.fromI32(value).times(power)) + power = power.times(BigInt.fromI32(16)) + } + return bigint +} diff --git a/src/uniswap/common/pricing.ts b/src/uniswap/common/pricing.ts new file mode 100644 index 0000000..b9e253c --- /dev/null +++ b/src/uniswap/common/pricing.ts @@ -0,0 +1,125 @@ +/* eslint-disable prefer-const */ +import { Address, BigDecimal, BigInt } from '@graphprotocol/graph-ts' + +import { Bundle, Pool, Token } from '../../../generated/schema' +import { MINIMUM_NATIVE_LOCKED, REFERENCE_TOKEN, STABLE_COINS, STABLE_TOKEN_POOL, WHITELIST_TOKENS } from './chain' +import { ONE_BD, ZERO_BD, ZERO_BI } from './constants' +import { exponentToBigDecimal, safeDiv } from './utils' + +let Q192 = BigInt.fromI32(2).pow(192 as u8) + +export function sqrtPriceX96ToTokenPrices(sqrtPriceX96: BigInt, token0: Token, token1: Token): BigDecimal[] { + let num = sqrtPriceX96.times(sqrtPriceX96).toBigDecimal() + let denom = BigDecimal.fromString(Q192.toString()) + let price1 = safeDiv( + safeDiv(num, denom).times(exponentToBigDecimal(token0.decimals)), + exponentToBigDecimal(token1.decimals) + ) + + let price0 = safeDiv(BigDecimal.fromString('1'), price1) + return [price0, price1] +} + +export function getEthPriceInUSD(): BigDecimal { + // fetch eth prices for each stablecoin + let stablePool = STABLE_TOKEN_POOL + let usdcPool = Pool.load(Address.fromString(stablePool)) // dai is token0 + if (usdcPool) { + if (usdcPool.token0 == Address.fromString(REFERENCE_TOKEN)) return usdcPool.token1Price + else return usdcPool.token0Price + } else { + return ZERO_BD + } +} + +/** + * Search through graph to find derived Eth per token. + * @todo update to be derived ETH (add stablecoin estimates) + **/ +export function findEthPerToken(token: Token): BigDecimal { + if (token.id == Address.fromString(REFERENCE_TOKEN)) { + return ONE_BD + } + let whiteList = token.whitelistPools + // for now just take USD from pool with greatest TVL + // need to update this to actually detect best rate based on liquidity distribution + let largestLiquidityETH = ZERO_BD + let priceSoFar = ZERO_BD + let bundle = Bundle.load('1')! + // hardcoded fix for incorrect rates + // if whitelist includes token - get the safe price + if (STABLE_COINS.includes(token.id.toHexString())) { + priceSoFar = safeDiv(ONE_BD, bundle.ethPriceUSD) + } else { + for (let i = 0; i < whiteList.length; ++i) { + const poolAddress = whiteList[i] + const pool = Pool.load(poolAddress) + + if (pool) { + if (pool.liquidity.gt(ZERO_BI)) { + if (pool.token0 == token.id) { + // whitelist token is token1 + const token1 = Token.load(pool.token1) + // get the derived ETH in pool + if (token1) { + const ethLocked = pool.totalValueLockedToken1.times(token1.derivedETH) + if (ethLocked.gt(largestLiquidityETH) && ethLocked.gt(MINIMUM_NATIVE_LOCKED)) { + largestLiquidityETH = ethLocked + // token1 per our token * Eth per token1 + priceSoFar = pool.token1Price.times(token1.derivedETH as BigDecimal) + } + } + } + if (pool.token1 == token.id) { + const token0 = Token.load(pool.token0) + // get the derived ETH in pool + if (token0) { + const ethLocked = pool.totalValueLockedToken0.times(token0.derivedETH) + if (ethLocked.gt(largestLiquidityETH) && ethLocked.gt(MINIMUM_NATIVE_LOCKED)) { + largestLiquidityETH = ethLocked + // token0 per our token * ETH per token0 + priceSoFar = pool.token0Price.times(token0.derivedETH as BigDecimal) + } + } + } + } + } + } + } + return priceSoFar // nothing was found return 0 +} + +/** + * Accepts tokens and amounts, return tracked amount based on token whitelist + * If one token on whitelist, return amount in that token converted to USD * 2. + * If both are, return sum of two amounts + * If neither is, return 0 + */ +export function getTrackedAmountUSD( + tokenAmount0: BigDecimal, + token0: Token, + tokenAmount1: BigDecimal, + token1: Token +): BigDecimal { + let bundle = Bundle.load('1')! + let price0USD = token0.derivedETH.times(bundle.ethPriceUSD) + let price1USD = token1.derivedETH.times(bundle.ethPriceUSD) + + // both are whitelist tokens, return sum of both amounts + if (WHITELIST_TOKENS.includes(token0.id.toHexString()) && WHITELIST_TOKENS.includes(token1.id.toHexString())) { + return tokenAmount0.times(price0USD).plus(tokenAmount1.times(price1USD)) + } + + // take double value of the whitelisted token amount + if (WHITELIST_TOKENS.includes(token0.id.toHexString()) && !WHITELIST_TOKENS.includes(token1.id.toHexString())) { + return tokenAmount0.times(price0USD).times(BigDecimal.fromString('2')) + } + + // take double value of the whitelisted token amount + if (!WHITELIST_TOKENS.includes(token0.id.toHexString()) && WHITELIST_TOKENS.includes(token1.id.toHexString())) { + return tokenAmount1.times(price1USD).times(BigDecimal.fromString('2')) + } + + // neither token is on white list, tracked amount is 0 + return ZERO_BD +} diff --git a/src/uniswap/common/staticTokenDefinition.ts b/src/uniswap/common/staticTokenDefinition.ts new file mode 100644 index 0000000..5918aeb --- /dev/null +++ b/src/uniswap/common/staticTokenDefinition.ts @@ -0,0 +1,20 @@ +import { Address } from '@graphprotocol/graph-ts' + +import { STATIC_TOKEN_DEFINITIONS, TokenDefinition } from './chain' + +// Helper for hardcoded tokens +export const getStaticDefinition = (tokenAddress: Address): TokenDefinition | null => { + const staticDefinitions = STATIC_TOKEN_DEFINITIONS + const tokenAddressHex = tokenAddress.toHexString() + + // Search the definition using the address + for (let i = 0; i < staticDefinitions.length; i++) { + const staticDefinition = staticDefinitions[i] + if (staticDefinition.address.toHexString().toLowerCase() == tokenAddressHex.toLowerCase()) { + return staticDefinition + } + } + + // If not found, return null + return null +} diff --git a/src/uniswap/common/tick.ts b/src/uniswap/common/tick.ts new file mode 100644 index 0000000..4dc6962 --- /dev/null +++ b/src/uniswap/common/tick.ts @@ -0,0 +1,58 @@ +import { BigDecimal, BigInt } from '@graphprotocol/graph-ts' + +import { Tick } from '../../../generated/schema' +import { Mint as MintEvent } from '../../../generated/templates/Pool/Pool' +import { ONE_BD, ZERO_BD, ZERO_BI } from './constants' +import { bigDecimalExponated, safeDiv } from './utils' + +export function createTick(tickId: string, tickIdx: i32, poolId: Bytes, event: MintEvent): Tick { + const tick = new Tick(tickId) + tick.tickIdx = BigInt.fromI32(tickIdx) + tick.pool = poolId + tick.poolAddress = poolId + + tick.createdAtTimestamp = event.block.timestamp + tick.createdAtBlockNumber = event.block.number + tick.liquidityGross = ZERO_BI + tick.liquidityNet = ZERO_BI + tick.liquidityProviderCount = ZERO_BI + + tick.price0 = ONE_BD + tick.price1 = ONE_BD + + // 1.0001^tick is token1/token0. + const price0 = bigDecimalExponated(BigDecimal.fromString('1.0001'), BigInt.fromI32(tickIdx)) + tick.price0 = price0 + tick.price1 = safeDiv(ONE_BD, price0) + + tick.volumeToken0 = ZERO_BD + tick.volumeToken1 = ZERO_BD + tick.volumeUSD = ZERO_BD + tick.feesUSD = ZERO_BD + tick.untrackedVolumeUSD = ZERO_BD + tick.collectedFeesToken0 = ZERO_BD + tick.collectedFeesToken1 = ZERO_BD + tick.collectedFeesUSD = ZERO_BD + tick.liquidityProviderCount = ZERO_BI + tick.feeGrowthOutside0X128 = ZERO_BI + tick.feeGrowthOutside1X128 = ZERO_BI + + return tick +} + +export function feeTierToTickSpacing(feeTier: BigInt): BigInt { + if (feeTier.equals(BigInt.fromI32(10000))) { + return BigInt.fromI32(200) + } + if (feeTier.equals(BigInt.fromI32(3000))) { + return BigInt.fromI32(60) + } + if (feeTier.equals(BigInt.fromI32(500))) { + return BigInt.fromI32(10) + } + if (feeTier.equals(BigInt.fromI32(100))) { + return BigInt.fromI32(1) + } + + throw Error('Unexpected fee tier') +} diff --git a/src/uniswap/common/token.ts b/src/uniswap/common/token.ts new file mode 100644 index 0000000..2b19f03 --- /dev/null +++ b/src/uniswap/common/token.ts @@ -0,0 +1,89 @@ +/* eslint-disable prefer-const */ +import { Address, BigInt } from '@graphprotocol/graph-ts' + +import { ERC20 } from '../../../generated/Factory/ERC20' +import { ERC20NameBytes } from '../../../generated/Factory/ERC20NameBytes' +import { ERC20SymbolBytes } from '../../../generated/Factory/ERC20SymbolBytes' +import { TokenDefinition } from './chain' +import { getStaticDefinition } from './staticTokenDefinition' +import { isNullEthValue } from './utils' + +export function fetchTokenSymbol(tokenAddress: Address): string { + let staticDefinition = getStaticDefinition(tokenAddress) + if (staticDefinition != null) { + return (staticDefinition as TokenDefinition).symbol + } + let contract = ERC20.bind(tokenAddress) + let contractSymbolBytes = ERC20SymbolBytes.bind(tokenAddress) + + // try types string and bytes32 for symbol + let symbolValue = 'unknown' + let symbolResult = contract.try_symbol() + if (symbolResult.reverted) { + let symbolResultBytes = contractSymbolBytes.try_symbol() + if (!symbolResultBytes.reverted) { + // for broken pairs that have no symbol function exposed + if (!isNullEthValue(symbolResultBytes.value.toHexString())) { + symbolValue = symbolResultBytes.value.toString() + } + } + } else { + symbolValue = symbolResult.value + } + + return symbolValue +} + +export function fetchTokenName(tokenAddress: Address): string { + let staticDefinition = getStaticDefinition(tokenAddress) + if (staticDefinition != null) { + return (staticDefinition as TokenDefinition).name + } + let contract = ERC20.bind(tokenAddress) + let contractNameBytes = ERC20NameBytes.bind(tokenAddress) + + // try types string and bytes32 for name + let nameValue = 'unknown' + let nameResult = contract.try_name() + if (nameResult.reverted) { + let nameResultBytes = contractNameBytes.try_name() + if (!nameResultBytes.reverted) { + // for broken exchanges that have no name function exposed + if (!isNullEthValue(nameResultBytes.value.toHexString())) { + nameValue = nameResultBytes.value.toString() + } + } + } else { + nameValue = nameResult.value + } + + return nameValue +} + +export function fetchTokenTotalSupply(tokenAddress: Address): BigInt { + let contract = ERC20.bind(tokenAddress) + let totalSupplyValue = BigInt.zero() + let totalSupplyResult = contract.try_totalSupply() + if (!totalSupplyResult.reverted) { + totalSupplyValue = totalSupplyResult.value + } + return totalSupplyValue +} + +export function fetchTokenDecimals(tokenAddress: Address): BigInt | null { + let staticDefinition = getStaticDefinition(tokenAddress) + if (staticDefinition != null) { + return (staticDefinition as TokenDefinition).decimals + } + let contract = ERC20.bind(tokenAddress) + // try types uint8 for decimals + + let decimalResult = contract.try_decimals() + if (!decimalResult.reverted) { + if (decimalResult.value.lt(BigInt.fromI32(255))) { + return decimalResult.value + } + } + + return null +} diff --git a/src/uniswap/common/utils.ts b/src/uniswap/common/utils.ts new file mode 100644 index 0000000..3b84fa0 --- /dev/null +++ b/src/uniswap/common/utils.ts @@ -0,0 +1,124 @@ +/* eslint-disable prefer-const */ +import { BigDecimal, BigInt } from '@graphprotocol/graph-ts' + +import { ONE_BD, ONE_BI, ZERO_BD, ZERO_BI } from './constants' + +export function exponentToBigDecimal(decimals: BigInt): BigDecimal { + let bd = BigDecimal.fromString('1') + + if (decimals < BigInt.fromI32(255)) { + bd = BigInt.fromI32(10) + .pow(decimals.toI32() as u8) + .toBigDecimal() + } + return bd +} + +// return 0 if denominator is 0 in division +export function safeDiv(amount0: BigDecimal, amount1: BigDecimal): BigDecimal { + if (amount1.equals(ZERO_BD)) { + return ZERO_BD + } else { + return amount0.div(amount1) + } +} + +export function safeDivBigInt(amount0: BigInt, amount1: BigInt): BigInt { + if (amount1.equals(ZERO_BI)) { + return ZERO_BI + } else { + return amount0.div(amount1) + } +} + +export function bigDecimalExponated(value: BigDecimal, power: BigInt): BigDecimal { + if (power.equals(ZERO_BI)) { + return ONE_BD + } + let negativePower = power.lt(ZERO_BI) + let result = ZERO_BD.plus(value) + let powerAbs = power.abs() + for (let i = ONE_BI; i.lt(powerAbs); i = i.plus(ONE_BI)) { + result = result.times(value) + } + + if (negativePower) { + result = safeDiv(ONE_BD, result) + } + + return result +} + +export function tokenAmountToDecimal(tokenAmount: BigInt, exchangeDecimals: BigInt): BigDecimal { + if (exchangeDecimals == ZERO_BI) { + return tokenAmount.toBigDecimal() + } + return tokenAmount.toBigDecimal().div(exponentToBigDecimal(exchangeDecimals)) +} + +export function priceToDecimal(amount: BigDecimal, exchangeDecimals: BigInt): BigDecimal { + if (exchangeDecimals == ZERO_BI) { + return amount + } + return safeDiv(amount, exponentToBigDecimal(exchangeDecimals)) +} + +export function equalToZero(value: BigDecimal): boolean { + const formattedVal = parseFloat(value.toString()) + const zero = parseFloat(ZERO_BD.toString()) + if (zero == formattedVal) { + return true + } + return false +} + +export function isNullEthValue(value: string): boolean { + return value == '0x0000000000000000000000000000000000000000000000000000000000000001' +} + +export function bigDecimalExp18(): BigDecimal { + return BigDecimal.fromString('1000000000000000000') +} + +export function convertTokenToDecimal(tokenAmount: BigInt, exchangeDecimals: BigInt): BigDecimal { + if (exchangeDecimals == ZERO_BI) { + return tokenAmount.toBigDecimal() + } + return tokenAmount.toBigDecimal().div(exponentToBigDecimal(exchangeDecimals)) +} + +export function convertEthToDecimal(eth: BigInt): BigDecimal { + return eth.toBigDecimal().div(exponentToBigDecimal(BigInt.fromI32(18))) +} + +/** + * Implements exponentiation by squaring + * (see https://en.wikipedia.org/wiki/Exponentiation_by_squaring ) + * to minimize the number of BigDecimal operations and their impact on performance. + */ +export function fastExponentiation(value: BigDecimal, power: i32): BigDecimal { + if (power < 0) { + const result = fastExponentiation(value, -power) + return safeDiv(ONE_BD, result) + } + + if (power == 0) { + return ONE_BD + } + + if (power == 1) { + return value + } + + const halfPower = power / 2 + const halfResult = fastExponentiation(value, halfPower) + + // Use the fact that x ^ (2n) = (x ^ n) * (x ^ n) and we can compute (x ^ n) only once. + let result = halfResult.times(halfResult) + + // For odd powers, x ^ (2n + 1) = (x ^ 2n) * x + if (power % 2 == 1) { + result = result.times(value) + } + return result +} diff --git a/src/uniswap/v3/mappings/burn.ts b/src/uniswap/v3/mappings/burn.ts new file mode 100644 index 0000000..813d807 --- /dev/null +++ b/src/uniswap/v3/mappings/burn.ts @@ -0,0 +1,106 @@ +import { BigInt } from '@graphprotocol/graph-ts' + +import { Bundle, Burn, Factory, Pool, Tick, Token } from '../../../../generated/schema' +import { Burn as BurnEvent } from '../../../../generated/templates/Pool/Pool' +import { FACTORY_ADDRESS } from '../../common/chain' +import { ONE_BI } from '../../common/constants' +import { convertTokenToDecimal } from '../../common/utils' +import { + updatePoolDayData, + updatePoolHourData, + updateTokenDayData, + updateTokenHourData, + updateUniswapDayData, +} from './intervalUpdates' +import { loadTransaction } from './utils' + +export function handleBurn(event: BurnEvent): void { + const factoryAddress = FACTORY_ADDRESS + + const bundle = Bundle.load('1')! + const pool = Pool.load(event.address)! + const factory = Factory.load(factoryAddress)! + + const token0 = Token.load(pool.token0) + const token1 = Token.load(pool.token1) + + if (token0 && token1) { + const amount0 = convertTokenToDecimal(event.params.amount0, token0.decimals) + const amount1 = convertTokenToDecimal(event.params.amount1, token1.decimals) + + const amountUSD = amount0 + .times(token0.derivedETH.times(bundle.ethPriceUSD)) + .plus(amount1.times(token1.derivedETH.times(bundle.ethPriceUSD))) + + // update globals + factory.txCount = factory.txCount.plus(ONE_BI) + + // update token0 data + token0.txCount = token0.txCount.plus(ONE_BI) + + // update token1 data + token1.txCount = token1.txCount.plus(ONE_BI) + + // pool data + pool.txCount = pool.txCount.plus(ONE_BI) + // Pools liquidity tracks the currently active liquidity given pools current tick. + // We only want to update it on burn if the position being burnt includes the current tick. + if ( + pool.tick !== null && + BigInt.fromI32(event.params.tickLower).le(pool.tick as BigInt) && + BigInt.fromI32(event.params.tickUpper).gt(pool.tick as BigInt) + ) { + // todo: this liquidity can be calculated from the real reserves and + // current price instead of incrementally from every burned amount which + // may not be accurate: https://linear.app/uniswap/issue/DAT-336/fix-pool-liquidity + pool.liquidity = pool.liquidity.minus(event.params.amount) + } + + // burn entity + const transaction = loadTransaction(event) + const burn = new Burn(transaction.id + '-' + event.logIndex.toString()) + burn.transaction = transaction.id + burn.timestamp = transaction.timestamp + burn.pool = pool.id + burn.token0 = pool.token0 + burn.token1 = pool.token1 + burn.owner = event.params.owner + burn.origin = event.transaction.from + burn.amount = event.params.amount + burn.amount0 = amount0 + burn.amount1 = amount1 + burn.amountUSD = amountUSD + burn.tickLower = BigInt.fromI32(event.params.tickLower) + burn.tickUpper = BigInt.fromI32(event.params.tickUpper) + burn.logIndex = event.logIndex + + // tick entities + const lowerTickId = pool.id.toHexString() + '#' + BigInt.fromI32(event.params.tickLower).toString() + const upperTickId = pool.id.toHexString() + '#' + BigInt.fromI32(event.params.tickUpper).toString() + const lowerTick = Tick.load(lowerTickId) + const upperTick = Tick.load(upperTickId) + if (lowerTick && upperTick) { + const amount = event.params.amount + lowerTick.liquidityGross = lowerTick.liquidityGross.minus(amount) + lowerTick.liquidityNet = lowerTick.liquidityNet.minus(amount) + upperTick.liquidityGross = upperTick.liquidityGross.minus(amount) + upperTick.liquidityNet = upperTick.liquidityNet.plus(amount) + + lowerTick.save() + upperTick.save() + } + updateUniswapDayData(event, factoryAddress) + updatePoolDayData(event) + updatePoolHourData(event) + updateTokenDayData(token0 as Token, event) + updateTokenDayData(token1 as Token, event) + updateTokenHourData(token0 as Token, event) + updateTokenHourData(token1 as Token, event) + + token0.save() + token1.save() + pool.save() + factory.save() + burn.save() + } +} diff --git a/src/uniswap/v3/mappings/collect.ts b/src/uniswap/v3/mappings/collect.ts new file mode 100644 index 0000000..8a24a9e --- /dev/null +++ b/src/uniswap/v3/mappings/collect.ts @@ -0,0 +1,105 @@ +import { BigInt } from '@graphprotocol/graph-ts' + +import { Bundle, Collect, Factory, Pool, Token } from '../../../../generated/schema' +import { Collect as CollectEvent } from '../../../../generated/templates/Pool/Pool' +import { FACTORY_ADDRESS } from '../../common/chain' +import { ONE_BI } from '../../common/constants' +import { getTrackedAmountUSD } from '../../common/pricing' +import { convertTokenToDecimal } from '../../common/utils' +import { + updatePoolDayData, + updatePoolHourData, + updateTokenDayData, + updateTokenHourData, + updateUniswapDayData, +} from './intervalUpdates' +import { loadTransaction } from './utils' + +export function handleCollect(event: CollectEvent): void { + const factoryAddress = FACTORY_ADDRESS + + const bundle = Bundle.load('1')! + const pool = Pool.load(event.address)! + if (pool == null) { + return + } + const transaction = loadTransaction(event) + const factory = Factory.load(factoryAddress)! + + const token0 = Token.load(pool.token0) + const token1 = Token.load(pool.token1) + if (token0 == null || token1 == null) { + return + } + + // Get formatted amounts collected. + const collectedAmountToken0 = convertTokenToDecimal(event.params.amount0, token0.decimals) + const collectedAmountToken1 = convertTokenToDecimal(event.params.amount1, token1.decimals) + const trackedCollectedAmountUSD = getTrackedAmountUSD( + collectedAmountToken0, + token0 as Token, + collectedAmountToken1, + token1 as Token + ) + + // Reset tvl aggregates until new amounts calculated + factory.totalValueLockedETH = factory.totalValueLockedETH.minus(pool.totalValueLockedETH) + + // Update globals + factory.txCount = factory.txCount.plus(ONE_BI) + + // update token data + token0.txCount = token0.txCount.plus(ONE_BI) + token0.totalValueLocked = token0.totalValueLocked.minus(collectedAmountToken0) + token0.totalValueLockedUSD = token0.totalValueLocked.times(token0.derivedETH.times(bundle.ethPriceUSD)) + + token1.txCount = token1.txCount.plus(ONE_BI) + token1.totalValueLocked = token1.totalValueLocked.minus(collectedAmountToken1) + token1.totalValueLockedUSD = token1.totalValueLocked.times(token1.derivedETH.times(bundle.ethPriceUSD)) + + // Adjust pool TVL based on amount collected. + pool.txCount = pool.txCount.plus(ONE_BI) + pool.totalValueLockedToken0 = pool.totalValueLockedToken0.minus(collectedAmountToken0) + pool.totalValueLockedToken1 = pool.totalValueLockedToken1.minus(collectedAmountToken1) + pool.totalValueLockedETH = pool.totalValueLockedToken0 + .times(token0.derivedETH) + .plus(pool.totalValueLockedToken1.times(token1.derivedETH)) + pool.totalValueLockedUSD = pool.totalValueLockedETH.times(bundle.ethPriceUSD) + + // Update aggregate fee collection values. + pool.collectedFeesToken0 = pool.collectedFeesToken0.plus(collectedAmountToken0) + pool.collectedFeesToken1 = pool.collectedFeesToken1.plus(collectedAmountToken1) + pool.collectedFeesUSD = pool.collectedFeesUSD.plus(trackedCollectedAmountUSD) + + // reset aggregates with new amounts + factory.totalValueLockedETH = factory.totalValueLockedETH.plus(pool.totalValueLockedETH) + factory.totalValueLockedUSD = factory.totalValueLockedETH.times(bundle.ethPriceUSD) + + const collect = new Collect(transaction.id + '-' + event.logIndex.toString()) + collect.transaction = transaction.id + collect.timestamp = event.block.timestamp + collect.pool = pool.id + collect.owner = event.params.owner + collect.amount0 = collectedAmountToken0 + collect.amount1 = collectedAmountToken1 + collect.amountUSD = trackedCollectedAmountUSD + collect.tickLower = BigInt.fromI32(event.params.tickLower) + collect.tickUpper = BigInt.fromI32(event.params.tickUpper) + collect.logIndex = event.logIndex + + updateUniswapDayData(event, factoryAddress) + updatePoolDayData(event) + updatePoolHourData(event) + updateTokenDayData(token0 as Token, event) + updateTokenDayData(token1 as Token, event) + updateTokenHourData(token0 as Token, event) + updateTokenHourData(token1 as Token, event) + + token0.save() + token1.save() + factory.save() + pool.save() + collect.save() + + return +} diff --git a/src/uniswap/v3/mappings/core.ts b/src/uniswap/v3/mappings/core.ts new file mode 100644 index 0000000..6b3a006 --- /dev/null +++ b/src/uniswap/v3/mappings/core.ts @@ -0,0 +1,7 @@ +import { handleBurn } from './burn' +import { handleCollect } from './collect' +import { handleInitialize } from './initialize' +import { handleMint } from './mint' +import { handleSwap } from './swap' + +export { handleBurn, handleCollect, handleInitialize, handleMint, handleSwap } diff --git a/src/uniswap/v3/mappings/factory.ts b/src/uniswap/v3/mappings/factory.ts new file mode 100644 index 0000000..a92083e --- /dev/null +++ b/src/uniswap/v3/mappings/factory.ts @@ -0,0 +1,152 @@ +import { BigInt, log } from '@graphprotocol/graph-ts' + +import { PoolCreated } from '../../../../generated/Factory/Factory' +import { Factory } from '../../../../generated/schema' +import { Bundle, Pool, Token } from '../../../../generated/schema' +import { Pool as PoolTemplate } from '../../../../generated/templates' +import { populateEmptyPools } from '../../common/backfill' +import { FACTORY_ADDRESS, POOL_MAPINGS, SKIP_POOLS, WHITELIST_TOKENS } from '../../common/chain' +import { fetchTokenDecimals, fetchTokenName, fetchTokenSymbol, fetchTokenTotalSupply } from '../../common/token' +import { ADDRESS_ZERO, ONE_BI, ZERO_BD, ZERO_BI } from '../../common/constants' + +export function handlePoolCreated(event: PoolCreated): void { + const factoryAddress = FACTORY_ADDRESS + const whitelistTokens = WHITELIST_TOKENS + const poolsToSkip = SKIP_POOLS + const poolMappings = POOL_MAPINGS + + // temp fix + if (poolsToSkip.includes(event.params.pool.toHexString())) { + return + } + + // load factory + let factory = Factory.load(factoryAddress) + if (factory === null) { + factory = new Factory(factoryAddress) + factory.poolCount = ZERO_BI + factory.totalVolumeETH = ZERO_BD + factory.totalVolumeUSD = ZERO_BD + factory.untrackedVolumeUSD = ZERO_BD + factory.totalFeesUSD = ZERO_BD + factory.totalFeesETH = ZERO_BD + factory.totalValueLockedETH = ZERO_BD + factory.totalValueLockedUSD = ZERO_BD + factory.totalValueLockedUSDUntracked = ZERO_BD + factory.totalValueLockedETHUntracked = ZERO_BD + factory.txCount = ZERO_BI + factory.owner = ADDRESS_ZERO + + // create new bundle for tracking eth price + const bundle = new Bundle('1') + bundle.ethPriceUSD = ZERO_BD + bundle.save() + + populateEmptyPools(event, poolMappings, whitelistTokens) + } + + factory.poolCount = factory.poolCount.plus(ONE_BI) + + const pool = new Pool(event.params.pool) as Pool + let token0 = Token.load(event.params.token0) + let token1 = Token.load(event.params.token1) + + // fetch info if null + if (token0 === null) { + token0 = new Token(event.params.token0) + token0.symbol = fetchTokenSymbol(event.params.token0) + token0.name = fetchTokenName(event.params.token0) + token0.totalSupply = fetchTokenTotalSupply(event.params.token0) + const decimals = fetchTokenDecimals(event.params.token0) + + // bail if we couldn't figure out the decimals + if (decimals === null) { + log.debug('mybug the decimal on token 0 was null', []) + return + } + + token0.decimals = decimals + token0.derivedETH = ZERO_BD + token0.volume = ZERO_BD + token0.volumeUSD = ZERO_BD + token0.feesUSD = ZERO_BD + token0.untrackedVolumeUSD = ZERO_BD + token0.totalValueLocked = ZERO_BD + token0.totalValueLockedUSD = ZERO_BD + token0.totalValueLockedUSDUntracked = ZERO_BD + token0.txCount = ZERO_BI + token0.poolCount = ZERO_BI + token0.whitelistPools = [] + } + + if (token1 === null) { + token1 = new Token(event.params.token1) + token1.symbol = fetchTokenSymbol(event.params.token1) + token1.name = fetchTokenName(event.params.token1) + token1.totalSupply = fetchTokenTotalSupply(event.params.token1) + const decimals = fetchTokenDecimals(event.params.token1) + // bail if we couldn't figure out the decimals + if (decimals === null) { + log.debug('mybug the decimal on token 0 was null', []) + return + } + token1.decimals = decimals + token1.derivedETH = ZERO_BD + token1.volume = ZERO_BD + token1.volumeUSD = ZERO_BD + token1.untrackedVolumeUSD = ZERO_BD + token1.feesUSD = ZERO_BD + token1.totalValueLocked = ZERO_BD + token1.totalValueLockedUSD = ZERO_BD + token1.totalValueLockedUSDUntracked = ZERO_BD + token1.txCount = ZERO_BI + token1.poolCount = ZERO_BI + token1.whitelistPools = [] + } + + // update white listed pools + if (whitelistTokens.includes(token0.id.toHexString())) { + const newPools = token1.whitelistPools + newPools.push(pool.id) + token1.whitelistPools = newPools + } + if (whitelistTokens.includes(token1.id.toHexString())) { + const newPools = token0.whitelistPools + newPools.push(pool.id) + token0.whitelistPools = newPools + } + + pool.token0 = token0.id + pool.token1 = token1.id + pool.feeTier = BigInt.fromI32(event.params.fee) + pool.createdAtTimestamp = event.block.timestamp + pool.createdAtBlockNumber = event.block.number + pool.liquidityProviderCount = ZERO_BI + pool.txCount = ZERO_BI + pool.liquidity = ZERO_BI + pool.sqrtPrice = ZERO_BI + pool.token0Price = ZERO_BD + pool.token1Price = ZERO_BD + pool.observationIndex = ZERO_BI + pool.totalValueLockedToken0 = ZERO_BD + pool.totalValueLockedToken1 = ZERO_BD + pool.totalValueLockedUSD = ZERO_BD + pool.totalValueLockedETH = ZERO_BD + pool.totalValueLockedUSDUntracked = ZERO_BD + pool.volumeToken0 = ZERO_BD + pool.volumeToken1 = ZERO_BD + pool.volumeUSD = ZERO_BD + pool.feesUSD = ZERO_BD + pool.untrackedVolumeUSD = ZERO_BD + + pool.collectedFeesToken0 = ZERO_BD + pool.collectedFeesToken1 = ZERO_BD + pool.collectedFeesUSD = ZERO_BD + + pool.save() + // create the tracked contract based on the template + PoolTemplate.create(event.params.pool) + token0.save() + token1.save() + factory.save() +} diff --git a/src/uniswap/v3/mappings/initialize.ts b/src/uniswap/v3/mappings/initialize.ts new file mode 100644 index 0000000..c8d4922 --- /dev/null +++ b/src/uniswap/v3/mappings/initialize.ts @@ -0,0 +1,34 @@ +import { BigInt } from '@graphprotocol/graph-ts' + +import { Bundle, Pool, Token } from '../../../../generated/schema' +import { Initialize } from '../../../../generated/templates/Pool/Pool' +import { findEthPerToken, getEthPriceInUSD } from '../../common/pricing' +import { updatePoolDayData, updatePoolHourData } from './intervalUpdates' + +export function handleInitialize(event: Initialize): void { + // update pool sqrt price and tick + const pool = Pool.load(event.address)! + pool.sqrtPrice = event.params.sqrtPriceX96 + pool.tick = BigInt.fromI32(event.params.tick) + pool.save() + + // update token prices + const token0 = Token.load(pool.token0) + const token1 = Token.load(pool.token1) + + // update ETH price now that prices could have changed + const bundle = Bundle.load('1')! + bundle.ethPriceUSD = getEthPriceInUSD() + bundle.save() + + updatePoolDayData(event) + updatePoolHourData(event) + + // update token prices + if (token0 && token1) { + token0.derivedETH = findEthPerToken(token0 as Token) + token1.derivedETH = findEthPerToken(token1 as Token) + token0.save() + token1.save() + } +} diff --git a/src/uniswap/v3/mappings/intervalUpdates.ts b/src/uniswap/v3/mappings/intervalUpdates.ts new file mode 100644 index 0000000..1409276 --- /dev/null +++ b/src/uniswap/v3/mappings/intervalUpdates.ts @@ -0,0 +1,205 @@ +import { Address, ethereum } from '@graphprotocol/graph-ts' + +import { + Bundle, + Factory, + Pool, + PoolDayData, + PoolHourData, + Token, + TokenDayData, + TokenHourData, + UniswapDayData, +} from '../../../../generated/schema' +import { ONE_BI, ZERO_BD, ZERO_BI } from '../../common/constants' + +/** + * Tracks global aggregate data over daily windows + * @param event + */ +export function updateUniswapDayData(event: ethereum.Event, factoryAddress: string): UniswapDayData { + const uniswap = Factory.load(factoryAddress)! + const timestamp = event.block.timestamp.toI32() + const dayID = timestamp / 86400 // rounded + const dayStartTimestamp = dayID * 86400 + let uniswapDayData = UniswapDayData.load(dayID.toString()) + if (uniswapDayData === null) { + uniswapDayData = new UniswapDayData(dayID.toString()) + uniswapDayData.date = dayStartTimestamp + uniswapDayData.volumeETH = ZERO_BD + uniswapDayData.volumeUSD = ZERO_BD + uniswapDayData.volumeUSDUntracked = ZERO_BD + uniswapDayData.feesUSD = ZERO_BD + } + uniswapDayData.tvlUSD = uniswap.totalValueLockedUSD + uniswapDayData.txCount = uniswap.txCount + uniswapDayData.save() + return uniswapDayData as UniswapDayData +} + +export function updatePoolDayData(event: ethereum.Event): PoolDayData { + const timestamp = event.block.timestamp.toI32() + const dayID = timestamp / 86400 + const dayStartTimestamp = dayID * 86400 + const dayPoolID = event.address.toHexString().concat('-').concat(dayID.toString()) + const pool = Pool.load(event.address)! + let poolDayData = PoolDayData.load(dayPoolID) + if (poolDayData === null) { + poolDayData = new PoolDayData(dayPoolID) + poolDayData.date = dayStartTimestamp + poolDayData.pool = pool.id + // things that dont get initialized always + poolDayData.volumeToken0 = ZERO_BD + poolDayData.volumeToken1 = ZERO_BD + poolDayData.volumeUSD = ZERO_BD + poolDayData.feesUSD = ZERO_BD + poolDayData.txCount = ZERO_BI + poolDayData.open = pool.token0Price + poolDayData.high = pool.token0Price + poolDayData.low = pool.token0Price + poolDayData.close = pool.token0Price + } + + if (pool.token0Price.gt(poolDayData.high)) { + poolDayData.high = pool.token0Price + } + if (pool.token0Price.lt(poolDayData.low)) { + poolDayData.low = pool.token0Price + } + + poolDayData.liquidity = pool.liquidity + poolDayData.sqrtPrice = pool.sqrtPrice + poolDayData.token0Price = pool.token0Price + poolDayData.token1Price = pool.token1Price + poolDayData.close = pool.token0Price + poolDayData.tick = pool.tick + poolDayData.tvlUSD = pool.totalValueLockedUSD + poolDayData.txCount = poolDayData.txCount.plus(ONE_BI) + poolDayData.save() + + return poolDayData as PoolDayData +} + +export function updatePoolHourData(event: ethereum.Event): PoolHourData { + const timestamp = event.block.timestamp.toI32() + const hourIndex = timestamp / 3600 // get unique hour within unix history + const hourStartUnix = hourIndex * 3600 // want the rounded effect + const hourPoolID = event.address.toHexString().concat('-').concat(hourIndex.toString()) + const pool = Pool.load(event.address)! + let poolHourData = PoolHourData.load(hourPoolID) + if (poolHourData === null) { + poolHourData = new PoolHourData(hourPoolID) + poolHourData.periodStartUnix = hourStartUnix + poolHourData.pool = pool.id + // things that dont get initialized always + poolHourData.volumeToken0 = ZERO_BD + poolHourData.volumeToken1 = ZERO_BD + poolHourData.volumeUSD = ZERO_BD + poolHourData.txCount = ZERO_BI + poolHourData.feesUSD = ZERO_BD + poolHourData.open = pool.token0Price + poolHourData.high = pool.token0Price + poolHourData.low = pool.token0Price + poolHourData.close = pool.token0Price + } + + if (pool.token0Price.gt(poolHourData.high)) { + poolHourData.high = pool.token0Price + } + if (pool.token0Price.lt(poolHourData.low)) { + poolHourData.low = pool.token0Price + } + + poolHourData.liquidity = pool.liquidity + poolHourData.sqrtPrice = pool.sqrtPrice + poolHourData.token0Price = pool.token0Price + poolHourData.token1Price = pool.token1Price + poolHourData.close = pool.token0Price + poolHourData.tick = pool.tick + poolHourData.tvlUSD = pool.totalValueLockedUSD + poolHourData.txCount = poolHourData.txCount.plus(ONE_BI) + poolHourData.save() + + // test + return poolHourData as PoolHourData +} + +export function updateTokenDayData(token: Token, event: ethereum.Event): TokenDayData { + const bundle = Bundle.load('1')! + const timestamp = event.block.timestamp.toI32() + const dayID = timestamp / 86400 + const dayStartTimestamp = dayID * 86400 + const tokenDayID = Address.fromBytes(token.id).toHexString().concat('-').concat(dayID.toString()) + const tokenPrice = token.derivedETH.times(bundle.ethPriceUSD) + + let tokenDayData = TokenDayData.load(tokenDayID) + if (tokenDayData === null) { + tokenDayData = new TokenDayData(tokenDayID) + tokenDayData.date = dayStartTimestamp + tokenDayData.token = token.id + tokenDayData.volume = ZERO_BD + tokenDayData.volumeUSD = ZERO_BD + tokenDayData.feesUSD = ZERO_BD + tokenDayData.untrackedVolumeUSD = ZERO_BD + tokenDayData.open = tokenPrice + tokenDayData.high = tokenPrice + tokenDayData.low = tokenPrice + tokenDayData.close = tokenPrice + } + + if (tokenPrice.gt(tokenDayData.high)) { + tokenDayData.high = tokenPrice + } + + if (tokenPrice.lt(tokenDayData.low)) { + tokenDayData.low = tokenPrice + } + + tokenDayData.close = tokenPrice + tokenDayData.priceUSD = token.derivedETH.times(bundle.ethPriceUSD) + tokenDayData.totalValueLocked = token.totalValueLocked + tokenDayData.totalValueLockedUSD = token.totalValueLockedUSD + tokenDayData.save() + + return tokenDayData as TokenDayData +} + +export function updateTokenHourData(token: Token, event: ethereum.Event): TokenHourData { + const bundle = Bundle.load('1')! + const timestamp = event.block.timestamp.toI32() + const hourIndex = timestamp / 3600 // get unique hour within unix history + const hourStartUnix = hourIndex * 3600 // want the rounded effect + const tokenHourID = Address.fromBytes(token.id).toHexString().concat('-').concat(hourIndex.toString()) + let tokenHourData = TokenHourData.load(tokenHourID) + const tokenPrice = token.derivedETH.times(bundle.ethPriceUSD) + + if (tokenHourData === null) { + tokenHourData = new TokenHourData(tokenHourID) + tokenHourData.periodStartUnix = hourStartUnix + tokenHourData.token = token.id + tokenHourData.volume = ZERO_BD + tokenHourData.volumeUSD = ZERO_BD + tokenHourData.untrackedVolumeUSD = ZERO_BD + tokenHourData.feesUSD = ZERO_BD + tokenHourData.open = tokenPrice + tokenHourData.high = tokenPrice + tokenHourData.low = tokenPrice + tokenHourData.close = tokenPrice + } + + if (tokenPrice.gt(tokenHourData.high)) { + tokenHourData.high = tokenPrice + } + + if (tokenPrice.lt(tokenHourData.low)) { + tokenHourData.low = tokenPrice + } + + tokenHourData.close = tokenPrice + tokenHourData.priceUSD = tokenPrice + tokenHourData.totalValueLocked = token.totalValueLocked + tokenHourData.totalValueLockedUSD = token.totalValueLockedUSD + tokenHourData.save() + + return tokenHourData as TokenHourData +} diff --git a/src/uniswap/v3/mappings/mint.ts b/src/uniswap/v3/mappings/mint.ts new file mode 100644 index 0000000..92b981c --- /dev/null +++ b/src/uniswap/v3/mappings/mint.ts @@ -0,0 +1,138 @@ +import { BigInt } from '@graphprotocol/graph-ts' + +import { Bundle, Factory, Mint, Pool, Tick, Token } from '../../../../generated/schema' +import { Mint as MintEvent } from '../../../../generated/templates/Pool/Pool' +import { FACTORY_ADDRESS } from '../../common/chain' +import { ONE_BI } from '../../common/constants' +import { convertTokenToDecimal } from '../../common/utils' +import { + updatePoolDayData, + updatePoolHourData, + updateTokenDayData, + updateTokenHourData, + updateUniswapDayData, +} from './intervalUpdates' +import { createTick } from './tick' +import { loadTransaction } from './utils' + +export function handleMint(event: MintEvent): void { + const factoryAddress = FACTORY_ADDRESS + + const bundle = Bundle.load('1')! + const pool = Pool.load(event.address)! + const factory = Factory.load(factoryAddress)! + + const token0 = Token.load(pool.token0) + const token1 = Token.load(pool.token1) + + if (token0 && token1) { + const amount0 = convertTokenToDecimal(event.params.amount0, token0.decimals) + const amount1 = convertTokenToDecimal(event.params.amount1, token1.decimals) + + const amountUSD = amount0 + .times(token0.derivedETH.times(bundle.ethPriceUSD)) + .plus(amount1.times(token1.derivedETH.times(bundle.ethPriceUSD))) + + // reset tvl aggregates until new amounts calculated + factory.totalValueLockedETH = factory.totalValueLockedETH.minus(pool.totalValueLockedETH) + + // update globals + factory.txCount = factory.txCount.plus(ONE_BI) + + // update token0 data + token0.txCount = token0.txCount.plus(ONE_BI) + token0.totalValueLocked = token0.totalValueLocked.plus(amount0) + token0.totalValueLockedUSD = token0.totalValueLocked.times(token0.derivedETH.times(bundle.ethPriceUSD)) + + // update token1 data + token1.txCount = token1.txCount.plus(ONE_BI) + token1.totalValueLocked = token1.totalValueLocked.plus(amount1) + token1.totalValueLockedUSD = token1.totalValueLocked.times(token1.derivedETH.times(bundle.ethPriceUSD)) + + // pool data + pool.txCount = pool.txCount.plus(ONE_BI) + + // Pools liquidity tracks the currently active liquidity given pools current tick. + // We only want to update it on mint if the new position includes the current tick. + if ( + pool.tick !== null && + BigInt.fromI32(event.params.tickLower).le(pool.tick as BigInt) && + BigInt.fromI32(event.params.tickUpper).gt(pool.tick as BigInt) + ) { + pool.liquidity = pool.liquidity.plus(event.params.amount) + } + + pool.totalValueLockedToken0 = pool.totalValueLockedToken0.plus(amount0) + pool.totalValueLockedToken1 = pool.totalValueLockedToken1.plus(amount1) + pool.totalValueLockedETH = pool.totalValueLockedToken0 + .times(token0.derivedETH) + .plus(pool.totalValueLockedToken1.times(token1.derivedETH)) + pool.totalValueLockedUSD = pool.totalValueLockedETH.times(bundle.ethPriceUSD) + + // reset aggregates with new amounts + factory.totalValueLockedETH = factory.totalValueLockedETH.plus(pool.totalValueLockedETH) + factory.totalValueLockedUSD = factory.totalValueLockedETH.times(bundle.ethPriceUSD) + + const transaction = loadTransaction(event) + const mint = new Mint(transaction.id.toString() + '-' + event.logIndex.toString()) + mint.transaction = transaction.id + mint.timestamp = transaction.timestamp + mint.pool = pool.id + mint.token0 = pool.token0 + mint.token1 = pool.token1 + mint.owner = event.params.owner + mint.sender = event.params.sender + mint.origin = event.transaction.from + mint.amount = event.params.amount + mint.amount0 = amount0 + mint.amount1 = amount1 + mint.amountUSD = amountUSD + mint.tickLower = BigInt.fromI32(event.params.tickLower) + mint.tickUpper = BigInt.fromI32(event.params.tickUpper) + mint.logIndex = event.logIndex + + // tick entities + const lowerTickIdx = event.params.tickLower + const upperTickIdx = event.params.tickUpper + + const lowerTickId = pool.id.toHexString() + '#' + BigInt.fromI32(event.params.tickLower).toString() + const upperTickId = pool.id.toHexString() + '#' + BigInt.fromI32(event.params.tickUpper).toString() + + let lowerTick = Tick.load(lowerTickId) + let upperTick = Tick.load(upperTickId) + + if (lowerTick === null) { + lowerTick = createTick(lowerTickId, lowerTickIdx, pool.id, event) + } + + if (upperTick === null) { + upperTick = createTick(upperTickId, upperTickIdx, pool.id, event) + } + + const amount = event.params.amount + lowerTick.liquidityGross = lowerTick.liquidityGross.plus(amount) + lowerTick.liquidityNet = lowerTick.liquidityNet.plus(amount) + upperTick.liquidityGross = upperTick.liquidityGross.plus(amount) + upperTick.liquidityNet = upperTick.liquidityNet.minus(amount) + + lowerTick.save() + upperTick.save() + + // TODO: Update Tick's volume, fees, and liquidity provider count. Computing these on the tick + // level requires reimplementing some of the swapping code from v3-core. + + updateUniswapDayData(event, factoryAddress) + updatePoolDayData(event) + updatePoolHourData(event) + updateTokenDayData(token0 as Token, event) + updateTokenDayData(token1 as Token, event) + updateTokenHourData(token0 as Token, event) + updateTokenHourData(token1 as Token, event) + + token0.save() + token1.save() + pool.save() + factory.save() + mint.save() + } +} diff --git a/src/uniswap/v3/mappings/swap.ts b/src/uniswap/v3/mappings/swap.ts new file mode 100644 index 0000000..5763921 --- /dev/null +++ b/src/uniswap/v3/mappings/swap.ts @@ -0,0 +1,208 @@ +import { BigDecimal, BigInt } from '@graphprotocol/graph-ts' + +import { Bundle, Factory, Pool, Swap, Token } from '../../../../generated/schema' +import { Swap as SwapEvent } from '../../../../generated/templates/Pool/Pool' +import { FACTORY_ADDRESS } from '../../common/chain' +import { ONE_BI, ZERO_BD } from '../../common/constants' +import { findEthPerToken, getEthPriceInUSD, getTrackedAmountUSD, sqrtPriceX96ToTokenPrices } from '../../common/pricing' +import { convertTokenToDecimal, safeDiv } from '../../common/utils' +import { + updatePoolDayData, + updatePoolHourData, + updateTokenDayData, + updateTokenHourData, + updateUniswapDayData, +} from './intervalUpdates' +import { loadTransaction } from './utils' + +export function handleSwap(event: SwapEvent): void { + const factoryAddress = FACTORY_ADDRESS + + const bundle = Bundle.load('1')! + const factory = Factory.load(factoryAddress)! + const pool = Pool.load(event.address)! + + // hot fix for bad pricing + if (pool.id.toHexString().toLowerCase() == '0x9663f2ca0454accad3e094448ea6f77443880454') { + return + } + + const token0 = Token.load(pool.token0) + const token1 = Token.load(pool.token1) + + if (token0 && token1) { + // amounts - 0/1 are token deltas: can be positive or negative + const amount0 = convertTokenToDecimal(event.params.amount0, token0.decimals) + const amount1 = convertTokenToDecimal(event.params.amount1, token1.decimals) + + // need absolute amounts for volume + let amount0Abs = amount0 + if (amount0.lt(ZERO_BD)) { + amount0Abs = amount0.times(BigDecimal.fromString('-1')) + } + let amount1Abs = amount1 + if (amount1.lt(ZERO_BD)) { + amount1Abs = amount1.times(BigDecimal.fromString('-1')) + } + + const amount0ETH = amount0Abs.times(token0.derivedETH) + const amount1ETH = amount1Abs.times(token1.derivedETH) + const amount0USD = amount0ETH.times(bundle.ethPriceUSD) + const amount1USD = amount1ETH.times(bundle.ethPriceUSD) + + // get amount that should be tracked only - div 2 because cant count both input and output as volume + const amountTotalUSDTracked = getTrackedAmountUSD(amount0Abs, token0 as Token, amount1Abs, token1 as Token).div( + BigDecimal.fromString('2') + ) + const amountTotalETHTracked = safeDiv(amountTotalUSDTracked, bundle.ethPriceUSD) + const amountTotalUSDUntracked = amount0USD.plus(amount1USD).div(BigDecimal.fromString('2')) + + const feesETH = amountTotalETHTracked.times(pool.feeTier.toBigDecimal()).div(BigDecimal.fromString('1000000')) + const feesUSD = amountTotalUSDTracked.times(pool.feeTier.toBigDecimal()).div(BigDecimal.fromString('1000000')) + + // global updates + factory.txCount = factory.txCount.plus(ONE_BI) + factory.totalVolumeETH = factory.totalVolumeETH.plus(amountTotalETHTracked) + factory.totalVolumeUSD = factory.totalVolumeUSD.plus(amountTotalUSDTracked) + factory.untrackedVolumeUSD = factory.untrackedVolumeUSD.plus(amountTotalUSDUntracked) + factory.totalFeesETH = factory.totalFeesETH.plus(feesETH) + factory.totalFeesUSD = factory.totalFeesUSD.plus(feesUSD) + + // reset aggregate tvl before individual pool tvl updates + const currentPoolTvlETH = pool.totalValueLockedETH + factory.totalValueLockedETH = factory.totalValueLockedETH.minus(currentPoolTvlETH) + + // pool volume + pool.volumeToken0 = pool.volumeToken0.plus(amount0Abs) + pool.volumeToken1 = pool.volumeToken1.plus(amount1Abs) + pool.volumeUSD = pool.volumeUSD.plus(amountTotalUSDTracked) + pool.untrackedVolumeUSD = pool.untrackedVolumeUSD.plus(amountTotalUSDUntracked) + pool.feesUSD = pool.feesUSD.plus(feesUSD) + pool.txCount = pool.txCount.plus(ONE_BI) + + // Update the pool with the new active liquidity, price, and tick. + pool.liquidity = event.params.liquidity + pool.tick = BigInt.fromI32(event.params.tick as i32) + pool.sqrtPrice = event.params.sqrtPriceX96 + pool.totalValueLockedToken0 = pool.totalValueLockedToken0.plus(amount0) + pool.totalValueLockedToken1 = pool.totalValueLockedToken1.plus(amount1) + + // update token0 data + token0.volume = token0.volume.plus(amount0Abs) + token0.totalValueLocked = token0.totalValueLocked.plus(amount0) + token0.volumeUSD = token0.volumeUSD.plus(amountTotalUSDTracked) + token0.untrackedVolumeUSD = token0.untrackedVolumeUSD.plus(amountTotalUSDUntracked) + token0.feesUSD = token0.feesUSD.plus(feesUSD) + token0.txCount = token0.txCount.plus(ONE_BI) + + // update token1 data + token1.volume = token1.volume.plus(amount1Abs) + token1.totalValueLocked = token1.totalValueLocked.plus(amount1) + token1.volumeUSD = token1.volumeUSD.plus(amountTotalUSDTracked) + token1.untrackedVolumeUSD = token1.untrackedVolumeUSD.plus(amountTotalUSDUntracked) + token1.feesUSD = token1.feesUSD.plus(feesUSD) + token1.txCount = token1.txCount.plus(ONE_BI) + + // updated pool ratess + const prices = sqrtPriceX96ToTokenPrices(pool.sqrtPrice, token0 as Token, token1 as Token) + pool.token0Price = prices[0] + pool.token1Price = prices[1] + pool.save() + + // update USD pricing + bundle.ethPriceUSD = getEthPriceInUSD() + bundle.save() + token0.derivedETH = findEthPerToken(token0 as Token) + token1.derivedETH = findEthPerToken(token1 as Token) + + /** + * Things afffected by new USD rates + */ + pool.totalValueLockedETH = pool.totalValueLockedToken0 + .times(token0.derivedETH) + .plus(pool.totalValueLockedToken1.times(token1.derivedETH)) + pool.totalValueLockedUSD = pool.totalValueLockedETH.times(bundle.ethPriceUSD) + + factory.totalValueLockedETH = factory.totalValueLockedETH.plus(pool.totalValueLockedETH) + factory.totalValueLockedUSD = factory.totalValueLockedETH.times(bundle.ethPriceUSD) + + token0.totalValueLockedUSD = token0.totalValueLocked.times(token0.derivedETH).times(bundle.ethPriceUSD) + token1.totalValueLockedUSD = token1.totalValueLocked.times(token1.derivedETH).times(bundle.ethPriceUSD) + + // create Swap event + const transaction = loadTransaction(event) + const swap = new Swap(transaction.id + '-' + event.logIndex.toString()) + swap.transaction = transaction.id + swap.timestamp = transaction.timestamp + swap.pool = pool.id + swap.token0 = pool.token0 + swap.token1 = pool.token1 + swap.sender = event.params.sender + swap.origin = event.transaction.from + swap.recipient = event.params.recipient + swap.amount0 = amount0 + swap.amount1 = amount1 + swap.amountUSD = amountTotalUSDTracked + swap.tick = BigInt.fromI32(event.params.tick as i32) + swap.sqrtPriceX96 = event.params.sqrtPriceX96 + swap.logIndex = event.logIndex + + // interval data + const uniswapDayData = updateUniswapDayData(event, factoryAddress) + const poolDayData = updatePoolDayData(event) + const poolHourData = updatePoolHourData(event) + const token0DayData = updateTokenDayData(token0 as Token, event) + const token1DayData = updateTokenDayData(token1 as Token, event) + const token0HourData = updateTokenHourData(token0 as Token, event) + const token1HourData = updateTokenHourData(token1 as Token, event) + + // update volume metrics + uniswapDayData.volumeETH = uniswapDayData.volumeETH.plus(amountTotalETHTracked) + uniswapDayData.volumeUSD = uniswapDayData.volumeUSD.plus(amountTotalUSDTracked) + uniswapDayData.feesUSD = uniswapDayData.feesUSD.plus(feesUSD) + + poolDayData.volumeUSD = poolDayData.volumeUSD.plus(amountTotalUSDTracked) + poolDayData.volumeToken0 = poolDayData.volumeToken0.plus(amount0Abs) + poolDayData.volumeToken1 = poolDayData.volumeToken1.plus(amount1Abs) + poolDayData.feesUSD = poolDayData.feesUSD.plus(feesUSD) + + poolHourData.volumeUSD = poolHourData.volumeUSD.plus(amountTotalUSDTracked) + poolHourData.volumeToken0 = poolHourData.volumeToken0.plus(amount0Abs) + poolHourData.volumeToken1 = poolHourData.volumeToken1.plus(amount1Abs) + poolHourData.feesUSD = poolHourData.feesUSD.plus(feesUSD) + + token0DayData.volume = token0DayData.volume.plus(amount0Abs) + token0DayData.volumeUSD = token0DayData.volumeUSD.plus(amountTotalUSDTracked) + token0DayData.untrackedVolumeUSD = token0DayData.untrackedVolumeUSD.plus(amountTotalUSDTracked) + token0DayData.feesUSD = token0DayData.feesUSD.plus(feesUSD) + + token0HourData.volume = token0HourData.volume.plus(amount0Abs) + token0HourData.volumeUSD = token0HourData.volumeUSD.plus(amountTotalUSDTracked) + token0HourData.untrackedVolumeUSD = token0HourData.untrackedVolumeUSD.plus(amountTotalUSDTracked) + token0HourData.feesUSD = token0HourData.feesUSD.plus(feesUSD) + + token1DayData.volume = token1DayData.volume.plus(amount1Abs) + token1DayData.volumeUSD = token1DayData.volumeUSD.plus(amountTotalUSDTracked) + token1DayData.untrackedVolumeUSD = token1DayData.untrackedVolumeUSD.plus(amountTotalUSDTracked) + token1DayData.feesUSD = token1DayData.feesUSD.plus(feesUSD) + + token1HourData.volume = token1HourData.volume.plus(amount1Abs) + token1HourData.volumeUSD = token1HourData.volumeUSD.plus(amountTotalUSDTracked) + token1HourData.untrackedVolumeUSD = token1HourData.untrackedVolumeUSD.plus(amountTotalUSDTracked) + token1HourData.feesUSD = token1HourData.feesUSD.plus(feesUSD) + + swap.save() + token0DayData.save() + token1DayData.save() + uniswapDayData.save() + poolDayData.save() + poolHourData.save() + token0HourData.save() + token1HourData.save() + poolHourData.save() + factory.save() + pool.save() + token0.save() + token1.save() + } +} diff --git a/src/uniswap/v3/mappings/tick.ts b/src/uniswap/v3/mappings/tick.ts new file mode 100644 index 0000000..d9f632f --- /dev/null +++ b/src/uniswap/v3/mappings/tick.ts @@ -0,0 +1,28 @@ +import { BigDecimal, BigInt, Bytes } from '@graphprotocol/graph-ts' + +import { Tick } from '../../../../generated/schema' +import { Mint as MintEvent } from '../../../../generated/templates/Pool/Pool' +import { ONE_BD, ZERO_BI } from '../../common/constants' +import { fastExponentiation, safeDiv } from '../../common/utils' + +export function createTick(tickId: string, tickIdx: i32, poolId: Bytes, event: MintEvent): Tick { + const tick = new Tick(tickId) + tick.tickIdx = BigInt.fromI32(tickIdx) + tick.pool = poolId + tick.poolAddress = poolId + + tick.createdAtTimestamp = event.block.timestamp + tick.createdAtBlockNumber = event.block.number + tick.liquidityGross = ZERO_BI + tick.liquidityNet = ZERO_BI + + tick.price0 = ONE_BD + tick.price1 = ONE_BD + + // 1.0001^tick is token1/token0. + const price0 = fastExponentiation(BigDecimal.fromString('1.0001'), tickIdx) + tick.price0 = price0 + tick.price1 = safeDiv(ONE_BD, price0) + + return tick +} diff --git a/src/uniswap/v3/mappings/utils.ts b/src/uniswap/v3/mappings/utils.ts new file mode 100644 index 0000000..28dc476 --- /dev/null +++ b/src/uniswap/v3/mappings/utils.ts @@ -0,0 +1,16 @@ +import { BigInt, ethereum } from '@graphprotocol/graph-ts' + +import { Transaction } from '../../../../generated/schema' + +export function loadTransaction(event: ethereum.Event): Transaction { + let transaction = Transaction.load(event.transaction.hash.toHexString()) + if (transaction === null) { + transaction = new Transaction(event.transaction.hash.toHexString()) + } + transaction.blockNumber = event.block.number + transaction.timestamp = event.block.timestamp + transaction.gasUsed = BigInt.zero() //needs to be moved to transaction receipt + transaction.gasPrice = event.transaction.gasPrice + transaction.save() + return transaction as Transaction +} diff --git a/src/uniswap/v3/schema.graphql b/src/uniswap/v3/schema.graphql new file mode 100644 index 0000000..9f69d41 --- /dev/null +++ b/src/uniswap/v3/schema.graphql @@ -0,0 +1,498 @@ +type Factory @entity { + # factory address + id: ID! + # amount of pools created + poolCount: BigInt! + # amoutn of transactions all time + txCount: BigInt! + # total volume all time in derived USD + totalVolumeUSD: BigDecimal! + # total volume all time in derived ETH + totalVolumeETH: BigDecimal! + # total swap fees all time in USD + totalFeesUSD: BigDecimal! + # total swap fees all time in USD + totalFeesETH: BigDecimal! + # all volume even through less reliable USD values + untrackedVolumeUSD: BigDecimal! + # TVL derived in USD + totalValueLockedUSD: BigDecimal! + # TVL derived in ETH + totalValueLockedETH: BigDecimal! + # TVL derived in USD untracked + totalValueLockedUSDUntracked: BigDecimal! + # TVL derived in ETH untracked + totalValueLockedETHUntracked: BigDecimal! + + # current owner of the factory + owner: ID! +} + +# stores for USD calculations +type Bundle @entity { + id: ID! + # price of ETH in usd + ethPriceUSD: BigDecimal! +} + +type Token @entity { + # token address + id: Bytes! + # token symbol + symbol: String! + # token name + name: String! + # token decimals + decimals: BigInt! + # token total supply + totalSupply: BigInt! + # volume in token units + volume: BigDecimal! + # volume in derived USD + volumeUSD: BigDecimal! + # volume in USD even on pools with less reliable USD values + untrackedVolumeUSD: BigDecimal! + # fees in USD + feesUSD: BigDecimal! + # transactions across all pools that include this token + txCount: BigInt! + # number of pools containing this token + poolCount: BigInt! + # liquidity across all pools in token units + totalValueLocked: BigDecimal! + # liquidity across all pools in derived USD + totalValueLockedUSD: BigDecimal! + # TVL derived in USD untracked + totalValueLockedUSDUntracked: BigDecimal! + # Note: for chains where ETH is not the native token, this will be the derived + # price of that chain's native token, effectively, this should be renamed + # derivedNative + derivedETH: BigDecimal! + # pools token is in that are white listed for USD pricing + whitelistPools: [Pool!]! + # derived fields + tokenDayData: [TokenDayData!]! @derivedFrom(field: "token") +} + +type Pool @entity { + # pool address + id: Bytes! + # creation + createdAtTimestamp: BigInt! + # block pool was created at + createdAtBlockNumber: BigInt! + # token0 + token0: Token! + # token1 + token1: Token! + # fee amount + feeTier: BigInt! + # in range liquidity + liquidity: BigInt! + # current price tracker + sqrtPrice: BigInt! + # token0 per token1 + token0Price: BigDecimal! + # token1 per token0 + token1Price: BigDecimal! + # current tick + tick: BigInt + # current observation index + observationIndex: BigInt! + # all time token0 swapped + volumeToken0: BigDecimal! + # all time token1 swapped + volumeToken1: BigDecimal! + # all time USD swapped + volumeUSD: BigDecimal! + # all time USD swapped, unfiltered for unreliable USD pools + untrackedVolumeUSD: BigDecimal! + # fees in USD + feesUSD: BigDecimal! + # all time number of transactions + txCount: BigInt! + # all time fees collected token0 + collectedFeesToken0: BigDecimal! + # all time fees collected token1 + collectedFeesToken1: BigDecimal! + # all time fees collected derived USD + collectedFeesUSD: BigDecimal! + # total token 0 across all ticks + totalValueLockedToken0: BigDecimal! + # total token 1 across all ticks + totalValueLockedToken1: BigDecimal! + # tvl derived ETH + totalValueLockedETH: BigDecimal! + # tvl USD + totalValueLockedUSD: BigDecimal! + # TVL derived in USD untracked + totalValueLockedUSDUntracked: BigDecimal! + # Fields used to help derived relationship + liquidityProviderCount: BigInt! # used to detect new exchanges + # hourly snapshots of pool data + poolHourData: [PoolHourData!]! @derivedFrom(field: "pool") + # daily snapshots of pool data + poolDayData: [PoolDayData!]! @derivedFrom(field: "pool") + # derived fields + mints: [Mint!]! @derivedFrom(field: "pool") + burns: [Burn!]! @derivedFrom(field: "pool") + swaps: [Swap!]! @derivedFrom(field: "pool") + collects: [Collect!]! @derivedFrom(field: "pool") + ticks: [Tick!]! @derivedFrom(field: "pool") +} + +type Tick @entity { + # format: # + id: ID! + # pool address + poolAddress: Bytes! + # tick index + tickIdx: BigInt! + # pointer to pool + pool: Pool! + # total liquidity pool has as tick lower or upper + liquidityGross: BigInt! + # how much liquidity changes when tick crossed + liquidityNet: BigInt! + # calculated price of token0 of tick within this pool - constant + price0: BigDecimal! + # calculated price of token1 of tick within this pool - constant + price1: BigDecimal! + # created time + createdAtTimestamp: BigInt! + # created block + createdAtBlockNumber: BigInt! +} + +type Transaction @entity { + # txn hash + id: ID! + # block txn was included in + blockNumber: BigInt! + # timestamp txn was confirmed + timestamp: BigInt! + # gas used during txn execution + gasUsed: BigInt! + gasPrice: BigInt! + # derived values + mints: [Mint]! @derivedFrom(field: "transaction") + burns: [Burn]! @derivedFrom(field: "transaction") + swaps: [Swap]! @derivedFrom(field: "transaction") + flashed: [Flash]! @derivedFrom(field: "transaction") + collects: [Collect]! @derivedFrom(field: "transaction") +} + +type Mint @entity { + # transaction hash + "#" + index in mints Transaction array + id: ID! + # which txn the mint was included in + transaction: Transaction! + # time of txn + timestamp: BigInt! + # pool position is within + pool: Pool! + # allow indexing by tokens + token0: Token! + # allow indexing by tokens + token1: Token! + # owner of position where liquidity minted to + owner: Bytes! + # the address that minted the liquidity + sender: Bytes + # txn origin + origin: Bytes! # the EOA that initiated the txn + # amount of liquidity minted + amount: BigInt! + # amount of token 0 minted + amount0: BigDecimal! + # amount of token 1 minted + amount1: BigDecimal! + # derived amount based on available prices of tokens + amountUSD: BigDecimal + # lower tick of the position + tickLower: BigInt! + # upper tick of the position + tickUpper: BigInt! + # order within the txn + logIndex: BigInt +} + +type Burn @entity { + # transaction hash + "#" + index in mints Transaction array + id: ID! + # txn burn was included in + transaction: Transaction! + # pool position is within + pool: Pool! + # allow indexing by tokens + token0: Token! + # allow indexing by tokens + token1: Token! + # need this to pull recent txns for specific token or pool + timestamp: BigInt! + # owner of position where liquidity was burned + owner: Bytes + # txn origin + origin: Bytes! # the EOA that initiated the txn + # amouny of liquidity burned + amount: BigInt! + # amount of token 0 burned + amount0: BigDecimal! + # amount of token 1 burned + amount1: BigDecimal! + # derived amount based on available prices of tokens + amountUSD: BigDecimal + # lower tick of position + tickLower: BigInt! + # upper tick of position + tickUpper: BigInt! + # position within the transactions + logIndex: BigInt +} + +type Swap @entity { + # transaction hash + "#" + index in swaps Transaction array + id: ID! + # pointer to transaction + transaction: Transaction! + # timestamp of transaction + timestamp: BigInt! + # pool swap occured within + pool: Pool! + # allow indexing by tokens + token0: Token! + # allow indexing by tokens + token1: Token! + # sender of the swap + sender: Bytes! + # recipient of the swap + recipient: Bytes! + # txn origin + origin: Bytes! # the EOA that initiated the txn + # delta of token0 swapped + amount0: BigDecimal! + # delta of token1 swapped + amount1: BigDecimal! + # derived info + amountUSD: BigDecimal! + # The sqrt(price) of the pool after the swap, as a Q64.96 + sqrtPriceX96: BigInt! + # the tick after the swap + tick: BigInt! + # index within the txn + logIndex: BigInt +} + +type Collect @entity { + # transaction hash + "#" + index in collect Transaction array + id: ID! + # pointer to txn + transaction: Transaction! + # timestamp of event + timestamp: BigInt! + # pool collect occured within + pool: Pool! + # owner of position collect was performed on + owner: Bytes + # amount of token0 collected + amount0: BigDecimal! + # amount of token1 collected + amount1: BigDecimal! + # derived amount based on available prices of tokens + amountUSD: BigDecimal + # lower tick of position + tickLower: BigInt! + # uppper tick of position + tickUpper: BigInt! + # index within the txn + logIndex: BigInt +} + +type Flash @entity { + # transaction hash + "-" + index in collect Transaction array + id: ID! + # pointer to txn + transaction: Transaction! + # timestamp of event + timestamp: BigInt! + # pool collect occured within + pool: Pool! + # sender of the flash + sender: Bytes! + # recipient of the flash + recipient: Bytes! + # amount of token0 flashed + amount0: BigDecimal! + # amount of token1 flashed + amount1: BigDecimal! + # derived amount based on available prices of tokens + amountUSD: BigDecimal! + # amount token0 paid for flash + amount0Paid: BigDecimal! + # amount token1 paid for flash + amount1Paid: BigDecimal! + # index within the txn + logIndex: BigInt +} + +# Data accumulated and condensed into day stats for all of Uniswap +type UniswapDayData @entity { + # timestamp rounded to current day by dividing by 86400 + id: ID! + # timestamp rounded to current day by dividing by 86400 + date: Int! + # total daily volume in Uniswap derived in terms of ETH + volumeETH: BigDecimal! + # total daily volume in Uniswap derived in terms of USD + volumeUSD: BigDecimal! + # total daily volume in Uniswap derived in terms of USD untracked + volumeUSDUntracked: BigDecimal! + # fees in USD + feesUSD: BigDecimal! + # number of daily transactions + txCount: BigInt! + # tvl in terms of USD + tvlUSD: BigDecimal! +} + +# Data accumulated and condensed into day stats for each pool +type PoolDayData @entity { + # timestamp rounded to current day by dividing by 86400 + id: ID! + # timestamp rounded to current day by dividing by 86400 + date: Int! + # pointer to pool + pool: Pool! + # in range liquidity at end of period + liquidity: BigInt! + # current price tracker at end of period + sqrtPrice: BigInt! + # price of token0 - derived from sqrtPrice + token0Price: BigDecimal! + # price of token1 - derived from sqrtPrice + token1Price: BigDecimal! + # current tick at end of period + tick: BigInt + # tvl derived in USD at end of period + tvlUSD: BigDecimal! + # volume in token0 + volumeToken0: BigDecimal! + # volume in token1 + volumeToken1: BigDecimal! + # volume in USD + volumeUSD: BigDecimal! + # fees in USD + feesUSD: BigDecimal! + # numebr of transactions during period + txCount: BigInt! + # opening price of token0 + open: BigDecimal! + # high price of token0 + high: BigDecimal! + # low price of token0 + low: BigDecimal! + # close price of token0 + close: BigDecimal! +} + +# hourly stats tracker for pool +type PoolHourData @entity { + # format: - + id: ID! + # unix timestamp for start of hour + periodStartUnix: Int! + # pointer to pool + pool: Pool! + # in range liquidity at end of period + liquidity: BigInt! + # current price tracker at end of period + sqrtPrice: BigInt! + # price of token0 - derived from sqrtPrice + token0Price: BigDecimal! + # price of token1 - derived from sqrtPrice + token1Price: BigDecimal! + # current tick at end of period + tick: BigInt + # tvl derived in USD at end of period + tvlUSD: BigDecimal! + # volume in token0 + volumeToken0: BigDecimal! + # volume in token1 + volumeToken1: BigDecimal! + # volume in USD + volumeUSD: BigDecimal! + # fees in USD + feesUSD: BigDecimal! + # numebr of transactions during period + txCount: BigInt! + # opening price of token0 + open: BigDecimal! + # high price of token0 + high: BigDecimal! + # low price of token0 + low: BigDecimal! + # close price of token0 + close: BigDecimal! +} + +type TokenDayData @entity { + # token address concatendated with date + id: ID! + # timestamp rounded to current day by dividing by 86400 + date: Int! + # pointer to token + token: Token! + # volume in token units + volume: BigDecimal! + # volume in derived USD + volumeUSD: BigDecimal! + # volume in USD even on pools with less reliable USD values + untrackedVolumeUSD: BigDecimal! + # liquidity across all pools in token units + totalValueLocked: BigDecimal! + # liquidity across all pools in derived USD + totalValueLockedUSD: BigDecimal! + # price at end of period in USD + priceUSD: BigDecimal! + # fees in USD + feesUSD: BigDecimal! + # opening price USD + open: BigDecimal! + # high price USD + high: BigDecimal! + # low price USD + low: BigDecimal! + # close price USD + close: BigDecimal! +} + +type TokenHourData @entity { + # token address concatendated with date + id: ID! + # unix timestamp for start of hour + periodStartUnix: Int! + # pointer to token + token: Token! + # volume in token units + volume: BigDecimal! + # volume in derived USD + volumeUSD: BigDecimal! + # volume in USD even on pools with less reliable USD values + untrackedVolumeUSD: BigDecimal! + # liquidity across all pools in token units + totalValueLocked: BigDecimal! + # liquidity across all pools in derived USD + totalValueLockedUSD: BigDecimal! + # price at end of period in USD + priceUSD: BigDecimal! + # fees in USD + feesUSD: BigDecimal! + # opening price USD + open: BigDecimal! + # high price USD + high: BigDecimal! + # low price USD + low: BigDecimal! + # close price USD + close: BigDecimal! +} diff --git a/subgraph.moksha.yaml b/subgraph.moksha.yaml index c6c57ef..49fee4f 100644 --- a/subgraph.moksha.yaml +++ b/subgraph.moksha.yaml @@ -14,6 +14,27 @@ schema: # block: dataSources: + - kind: ethereum/contract + name: Bootstrap + network: moksha + source: + address: "0x0000000000000000000000000000000000000000" # dummy + abi: Bootstrap + startBlock: 655081 + endBlock: 655081 + mapping: + kind: ethereum/events + apiVersion: 0.0.6 + language: wasm/assemblyscript + entities: + - Epoch + - Dlp + abis: + - name: Bootstrap + file: ./abis/v1/empty.json + blockHandlers: + - handler: handleBootstrap + file: ./src/lib/entity/bootstrap/bootstrap.ts # v1 - kind: ethereum/contract name: DataRegistryImplementationV1 @@ -159,14 +180,10 @@ dataSources: handler: handleDlpUpdatedV5 - event: DlpStatusUpdated(indexed uint256,uint8) handler: handleDlpStatusUpdatedV5 - - event: DlpVerificationUpdated(indexed uint256,bool) - handler: handleDlpVerificationUpdatedV5 + - event: DlpVerificationBlockUpdated(indexed uint256,uint256) + handler: handleDlpVerificationBlockUpdatedV5 - event: DlpTokenUpdated(indexed uint256,address) handler: handleDlpTokenUpdatedV5 - - event: DlpSubEligibilityThresholdUpdated(uint256) - handler: handleDlpSubEligibilityThresholdUpdatedV5 - - event: DlpRegistrationDepositAmountUpdated(uint256) - handler: handleDlpRegistrationDepositAmountUpdatedV5 file: ./src/mapping.ts - kind: ethereum/contract @@ -237,7 +254,7 @@ dataSources: entities: - Permission - User - - TrustedServer + - Server abis: - name: DataPermissionImplementation file: ./abis/v5/DataPermissionImplementation.json @@ -274,4 +291,69 @@ dataSources: handler: handleFileAddedV3 - event: ProofAdded(indexed uint256,indexed address,uint256,indexed uint256,uint256,string) handler: handleDataRegistryProofAddedV3 + file: ./src/mapping.ts + + - kind: ethereum/contract + name: Factory + network: moksha + source: + address: "0x7067Eb594d6dc6a5AD33c3fcFCa7183F369bC2e8" + abi: Factory + startBlock: 596576 + mapping: + kind: ethereum/events + apiVersion: 0.0.6 + language: wasm/assemblyscript + entities: + - Pool + - Token + abis: + - name: Factory + file: ./abis/uniswap/factory.json + - name: ERC20 + file: ./abis/uniswap/ERC20.json + - name: ERC20SymbolBytes + file: ./abis/uniswap/ERC20SymbolBytes.json + - name: ERC20NameBytes + file: ./abis/uniswap/ERC20NameBytes.json + - name: Pool + file: ./abis/uniswap/pool.json + eventHandlers: + - event: PoolCreated(indexed address,indexed address,indexed uint24,int24,address) + handler: handlePoolCreated + file: ./src/mapping.ts + +templates: + - kind: ethereum/contract + name: Pool + network: moksha + source: + abi: Pool + mapping: + kind: ethereum/events + apiVersion: 0.0.6 + language: wasm/assemblyscript + entities: + - Pool + - Token + abis: + - name: Pool + file: ./abis/uniswap/pool.json + - name: Factory + file: ./abis/uniswap/factory.json + - name: ERC20 + file: ./abis/uniswap/ERC20.json + eventHandlers: + - event: Initialize(uint160,int24) + handler: handleInitialize + - event: Swap(indexed address,indexed address,int256,int256,uint160,uint128,int24) + handler: handleSwap + - event: Mint(address,indexed address,indexed int24,indexed + int24,uint128,uint256,uint256) + handler: handleMint + - event: Burn(indexed address,indexed int24,indexed int24,uint128,uint256,uint256) + handler: handleBurn + - event: Collect(indexed address,address,indexed int24,indexed + int24,uint128,uint128) + handler: handleCollect file: ./src/mapping.ts \ No newline at end of file diff --git a/subgraph.vana-moksha.yaml b/subgraph.vana-moksha.yaml index ff7305e..8ceab75 100644 --- a/subgraph.vana-moksha.yaml +++ b/subgraph.vana-moksha.yaml @@ -14,6 +14,27 @@ schema: # block: dataSources: + - kind: ethereum/contract + name: Bootstrap + network: vana-moksha + source: + address: "0x0000000000000000000000000000000000000000" # dummy + abi: Bootstrap + startBlock: 655081 + endBlock: 655081 + mapping: + kind: ethereum/events + apiVersion: 0.0.6 + language: wasm/assemblyscript + entities: + - Epoch + - Dlp + abis: + - name: Bootstrap + file: ./abis/v1/empty.json + blockHandlers: + - handler: handleBootstrap + file: ./src/lib/entity/bootstrap/bootstrap.ts # v1 - kind: ethereum/contract name: DataRegistryImplementationV1 @@ -159,8 +180,8 @@ dataSources: handler: handleDlpUpdatedV5 - event: DlpStatusUpdated(indexed uint256,uint8) handler: handleDlpStatusUpdatedV5 - - event: DlpVerificationUpdated(indexed uint256,bool) - handler: handleDlpVerificationUpdatedV5 + - event: DlpVerificationBlockUpdated(indexed uint256,uint256) + handler: handleDlpVerificationBlockUpdatedV5 - event: DlpTokenUpdated(indexed uint256,address) handler: handleDlpTokenUpdatedV5 - event: DlpSubEligibilityThresholdUpdated(uint256) @@ -237,7 +258,7 @@ dataSources: entities: - Permission - User - - TrustedServer + - Server abis: - name: DataPermissionImplementation file: ./abis/v5/DataPermissionImplementation.json @@ -274,4 +295,69 @@ dataSources: handler: handleFileAddedV3 - event: ProofAdded(indexed uint256,indexed address,uint256,indexed uint256,uint256,string) handler: handleDataRegistryProofAddedV3 + file: ./src/mapping.ts + + - kind: ethereum/contract + name: Factory + network: vana-moksha + source: + address: "0x7067Eb594d6dc6a5AD33c3fcFCa7183F369bC2e8" + abi: Factory + startBlock: 596576 + mapping: + kind: ethereum/events + apiVersion: 0.0.6 + language: wasm/assemblyscript + entities: + - Pool + - Token + abis: + - name: Factory + file: ./abis/uniswap/factory.json + - name: ERC20 + file: ./abis/uniswap/ERC20.json + - name: ERC20SymbolBytes + file: ./abis/uniswap/ERC20SymbolBytes.json + - name: ERC20NameBytes + file: ./abis/uniswap/ERC20NameBytes.json + - name: Pool + file: ./abis/uniswap/pool.json + eventHandlers: + - event: PoolCreated(indexed address,indexed address,indexed uint24,int24,address) + handler: handlePoolCreated + file: ./src/mapping.ts + +templates: + - kind: ethereum/contract + name: Pool + network: vana-moksha + source: + abi: Pool + mapping: + kind: ethereum/events + apiVersion: 0.0.6 + language: wasm/assemblyscript + entities: + - Pool + - Token + abis: + - name: Pool + file: ./abis/uniswap/pool.json + - name: Factory + file: ./abis/uniswap/factory.json + - name: ERC20 + file: ./abis/uniswap/ERC20.json + eventHandlers: + - event: Initialize(uint160,int24) + handler: handleInitialize + - event: Swap(indexed address,indexed address,int256,int256,uint160,uint128,int24) + handler: handleSwap + - event: Mint(address,indexed address,indexed int24,indexed + int24,uint128,uint256,uint256) + handler: handleMint + - event: Burn(indexed address,indexed int24,indexed int24,uint128,uint256,uint256) + handler: handleBurn + - event: Collect(indexed address,address,indexed int24,indexed + int24,uint128,uint128) + handler: handleCollect file: ./src/mapping.ts \ No newline at end of file diff --git a/subgraph.vana.yaml b/subgraph.vana.yaml index 5b69dd6..1515a12 100644 --- a/subgraph.vana.yaml +++ b/subgraph.vana.yaml @@ -14,6 +14,27 @@ schema: # block: dataSources: + - kind: ethereum/contract + name: Bootstrap + network: vana + source: + address: "0x0000000000000000000000000000000000000000" # dummy + abi: Bootstrap + startBlock: 700000 + endBlock: 700000 + mapping: + kind: ethereum/events + apiVersion: 0.0.6 + language: wasm/assemblyscript + entities: + - Epoch + - Dlp + abis: + - name: Bootstrap + file: ./abis/v1/empty.json + blockHandlers: + - handler: handleBootstrap + file: ./src/lib/entity/bootstrap/bootstrap.ts # v1 - kind: ethereum/contract name: DataRegistryImplementationV1 @@ -90,7 +111,7 @@ dataSources: handler: handleDataRegistryProofAddedV3 file: ./src/mapping.ts -# v4 + # v4 - kind: ethereum/contract name: QueryEngineImplementation network: vana @@ -133,7 +154,7 @@ dataSources: handler: handleRefinerAdded file: ./src/mapping.ts -#v5 + #v5 - kind: ethereum/contract name: DLPRegistryImplementationV5 network: vana @@ -159,14 +180,10 @@ dataSources: handler: handleDlpUpdatedV5 - event: DlpStatusUpdated(indexed uint256,uint8) handler: handleDlpStatusUpdatedV5 - - event: DlpVerificationUpdated(indexed uint256,bool) - handler: handleDlpVerificationUpdatedV5 + - event: DlpVerificationBlockUpdated(indexed uint256,uint256) + handler: handleDlpVerificationBlockUpdatedV5 - event: DlpTokenUpdated(indexed uint256,address) handler: handleDlpTokenUpdatedV5 - - event: DlpSubEligibilityThresholdUpdated(uint256) - handler: handleDlpSubEligibilityThresholdUpdatedV5 - - event: DlpRegistrationDepositAmountUpdated(uint256) - handler: handleDlpRegistrationDepositAmountUpdatedV5 file: ./src/mapping.ts - kind: ethereum/contract @@ -237,7 +254,7 @@ dataSources: entities: - Permission - User - - TrustedServer + - Server abis: - name: DataPermissionImplementation file: ./abis/v5/DataPermissionImplementation.json @@ -274,4 +291,69 @@ dataSources: handler: handleFileAddedV3 - event: ProofAdded(indexed uint256,indexed address,uint256,indexed uint256,uint256,string) handler: handleDataRegistryProofAddedV3 + file: ./src/mapping.ts + + - kind: ethereum/contract + name: Factory + network: vana + source: + address: "0xc2a0d530e57B1275fbce908031DA636f95EA1E38" + abi: Factory + startBlock: 763744 + mapping: + kind: ethereum/events + apiVersion: 0.0.6 + language: wasm/assemblyscript + entities: + - Pool + - Token + abis: + - name: Factory + file: ./abis/uniswap/factory.json + - name: ERC20 + file: ./abis/uniswap/ERC20.json + - name: ERC20SymbolBytes + file: ./abis/uniswap/ERC20SymbolBytes.json + - name: ERC20NameBytes + file: ./abis/uniswap/ERC20NameBytes.json + - name: Pool + file: ./abis/uniswap/pool.json + eventHandlers: + - event: PoolCreated(indexed address,indexed address,indexed uint24,int24,address) + handler: handlePoolCreated + file: ./src/mapping.ts + +templates: + - kind: ethereum/contract + name: Pool + network: vana + source: + abi: Pool + mapping: + kind: ethereum/events + apiVersion: 0.0.6 + language: wasm/assemblyscript + entities: + - Pool + - Token + abis: + - name: Pool + file: ./abis/uniswap/pool.json + - name: Factory + file: ./abis/uniswap/factory.json + - name: ERC20 + file: ./abis/uniswap/ERC20.json + eventHandlers: + - event: Initialize(uint160,int24) + handler: handleInitialize + - event: Swap(indexed address,indexed address,int256,int256,uint160,uint128,int24) + handler: handleSwap + - event: Mint(address,indexed address,indexed int24,indexed + int24,uint128,uint256,uint256) + handler: handleMint + - event: Burn(indexed address,indexed int24,indexed int24,uint128,uint256,uint256) + handler: handleBurn + - event: Collect(indexed address,address,indexed int24,indexed + int24,uint128,uint128) + handler: handleCollect file: ./src/mapping.ts \ No newline at end of file diff --git a/tests/unit/contract/utils/file-owner.ts b/tests/unit/contract/utils/file-owner.ts index 1af6280..ac163ee 100644 --- a/tests/unit/contract/utils/file-owner.ts +++ b/tests/unit/contract/utils/file-owner.ts @@ -1,17 +1,23 @@ -import { FileOwner } from "../../../../generated/schema"; -import { Address } from "@graphprotocol/graph-ts"; +import { Address, BigInt } from "@graphprotocol/graph-ts"; +import { File } from "../../../../generated/schema"; -export function fileOwnerDefaults(id: string, ownerAddress: string): FileOwner { - const file = new FileOwner(id); - file.ownerAddress = Address.fromString(ownerAddress); +export function fileDefaults(id: string, ownerAddress: string, url: string): File { + const file = new File(id); + file.owner = ownerAddress; + file.url = url; + file.schemaId = BigInt.zero(); + file.addedAtBlock = BigInt.zero(); + file.addedAtTimestamp = BigInt.zero(); + file.transactionHash = Address.zero(); return file; } -export function createNewFileOwner( +export function createNewFile( id: string, ownerAddress: string, -): FileOwner { - const file = fileOwnerDefaults(id, ownerAddress); + url: string, +): File { + const file = fileDefaults(id, ownerAddress, url); file.save(); return file; } diff --git a/tests/unit/contract/v1/data-registry-refactored.test.ts b/tests/unit/contract/v1/data-registry-refactored.test.ts new file mode 100644 index 0000000..4b6dd6c --- /dev/null +++ b/tests/unit/contract/v1/data-registry-refactored.test.ts @@ -0,0 +1,137 @@ +import { + assert, + beforeEach, + clearStore, + describe, + test, +} from "matchstick-as/assembly/index"; +import { BigInt as GraphBigInt } from "@graphprotocol/graph-ts"; +import { + handleFileAddedV1, + handleDataRegistryProofAddedV1 +} from "../../../../src/lib/contract/v1/data-registry"; +import { createFileAddedEvent } from "./utils/data-registry-events"; +import { createProofAddedEvent } from "./utils/data-registry-events"; +import { createNewEpoch, createNewEpochReference } from "../utils"; +import { EPOCH_REFERENCE_ID_CURRENT } from "../../../../src/lib/entity/epoch"; + +// Hook to clear the store before each test +beforeEach(() => { + clearStore(); +}); + +describe("V1 Data Registry Refactored Handlers", () => { + test("handleFileAddedV1 creates File and User entities using shared utilities", () => { + // ARRANGE + const fileId = 1; + const ownerAddress = "0x1234567890123456789012345678901234567890"; + const url = "ipfs://QmTest123"; + + const fileAddedEvent = createFileAddedEvent(fileId, ownerAddress, url); + + // ACT + handleFileAddedV1(fileAddedEvent); + + // ASSERT + // Check that File entity was created with correct properties + assert.entityCount("File", 1); + assert.fieldEquals("File", fileId.toString(), "id", fileId.toString()); + assert.fieldEquals("File", fileId.toString(), "owner", ownerAddress); + assert.fieldEquals("File", fileId.toString(), "url", url); + assert.fieldEquals("File", fileId.toString(), "schemaId", "0"); // V1 should use default schema ID + assert.fieldEquals("File", fileId.toString(), "addedAtBlock", fileAddedEvent.block.number.toString()); + assert.fieldEquals("File", fileId.toString(), "addedAtTimestamp", fileAddedEvent.block.timestamp.toString()); + assert.fieldEquals("File", fileId.toString(), "transactionHash", fileAddedEvent.transaction.hash.toHexString()); + + // Check that User entity was created + assert.entityCount("User", 1); + assert.fieldEquals("User", ownerAddress, "id", ownerAddress); + }); + + test("handleDataRegistryProofAddedV1 creates proof and updates totals using shared utilities", () => { + // ARRANGE + const fileId = 1; + const ownerAddress = "0x1234567890123456789012345678901234567890"; + const url = "ipfs://QmTest123"; + const proofIndex = 0; + + // Create required entities first + const fileEvent = createFileAddedEvent(fileId, ownerAddress, url); + handleFileAddedV1(fileEvent); + + // Create epoch entities + createNewEpoch("1"); + createNewEpochReference(EPOCH_REFERENCE_ID_CURRENT, "1"); + + const proofEvent = createProofAddedEvent(fileId, proofIndex); + + // ACT + handleDataRegistryProofAddedV1(proofEvent); + + // ASSERT + // Check that DataRegistryProof entity was created + assert.entityCount("DataRegistryProof", 1); + const proofId = proofEvent.transaction.hash.toHexString(); + assert.fieldEquals("DataRegistryProof", proofId, "id", proofId); + assert.fieldEquals("DataRegistryProof", proofId, "epoch", "1"); + assert.fieldEquals("DataRegistryProof", proofId, "fileId", fileId.toString()); + assert.fieldEquals("DataRegistryProof", proofId, "proofIndex", proofIndex.toString()); + assert.fieldEquals("DataRegistryProof", proofId, "createdAt", proofEvent.block.timestamp.toString()); + assert.fieldEquals("DataRegistryProof", proofId, "createdAtBlock", proofEvent.block.number.toString()); + assert.fieldEquals("DataRegistryProof", proofId, "createdTxHash", proofEvent.transaction.hash.toHexString()); + + // Check that totals were updated (V1 only has global totals) + assert.entityCount("Totals", 1); + assert.fieldEquals("Totals", "global", "totalFileContributions", "1"); + assert.fieldEquals("Totals", "global", "uniqueFileContributors", "1"); + + // Check that UserTotals was created + assert.entityCount("UserTotals", 1); + const userTotalsId = `user-${ownerAddress}`; + assert.fieldEquals("UserTotals", userTotalsId, "fileContributionsCount", "1"); + }); + + test("handleDataRegistryProofAddedV1 handles missing epoch gracefully", () => { + // ARRANGE + const fileId = 1; + const ownerAddress = "0x1234567890123456789012345678901234567890"; + const url = "ipfs://QmTest123"; + const proofIndex = 0; + + // Create file but NO epoch + const fileEvent = createFileAddedEvent(fileId, ownerAddress, url); + handleFileAddedV1(fileEvent); + + const proofEvent = createProofAddedEvent(fileId, proofIndex); + + // ACT + handleDataRegistryProofAddedV1(proofEvent); + + // ASSERT + // Should not create any proof or totals when epoch is missing + assert.entityCount("DataRegistryProof", 0); + assert.entityCount("Totals", 0); + assert.entityCount("UserTotals", 0); + }); + + test("handleDataRegistryProofAddedV1 handles missing file gracefully", () => { + // ARRANGE + const fileId = 999; // Non-existent file + const proofIndex = 0; + + // Create epoch but NO file + createNewEpoch("1"); + createNewEpochReference(EPOCH_REFERENCE_ID_CURRENT, "1"); + + const proofEvent = createProofAddedEvent(fileId, proofIndex); + + // ACT + handleDataRegistryProofAddedV1(proofEvent); + + // ASSERT + // Should create proof but not update totals when file is missing + assert.entityCount("DataRegistryProof", 1); + assert.entityCount("Totals", 0); + assert.entityCount("UserTotals", 0); + }); +}); \ No newline at end of file diff --git a/tests/unit/contract/v1/data-registry.test.ts b/tests/unit/contract/v1/data-registry.test.ts index bfeb5af..7f94ac7 100644 --- a/tests/unit/contract/v1/data-registry.test.ts +++ b/tests/unit/contract/v1/data-registry.test.ts @@ -15,7 +15,7 @@ beforeEach(() => { }); describe("handleFileAddedV1", () => { - test("creates both a File and a FileOwner entity", () => { + test("creates a File entity and associated User", () => { // 1. ARRANGE: Set up test data and create the mock event const fileId = 1; const ownerAddress = "0x1234567890123456789012345678901234567890"; @@ -28,7 +28,7 @@ describe("handleFileAddedV1", () => { // 3. ASSERT: Check that the store is in the correct state - // --- Assert the NEW functionality --- + // Check that a File entity was created assert.entityCount("File", 1); assert.fieldEquals("File", fileId.toString(), "id", fileId.toString()); assert.fieldEquals("File", fileId.toString(), "owner", ownerAddress); @@ -41,18 +41,8 @@ describe("handleFileAddedV1", () => { fileAddedEvent.transaction.hash.toHexString(), ); - // Also check that the associated User was created + // Check that the associated User was created assert.entityCount("User", 1); assert.fieldEquals("User", ownerAddress, "id", ownerAddress); - - // --- Assert the ORIGINAL functionality (prevents regression) --- - assert.entityCount("FileOwner", 1); - assert.fieldEquals("FileOwner", fileId.toString(), "id", fileId.toString()); - assert.fieldEquals( - "FileOwner", - fileId.toString(), - "ownerAddress", - ownerAddress, - ); }); }); diff --git a/tests/unit/contract/v1/utils/data-registry-events.ts b/tests/unit/contract/v1/utils/data-registry-events.ts index 8e8a3fd..c3da23d 100644 --- a/tests/unit/contract/v1/utils/data-registry-events.ts +++ b/tests/unit/contract/v1/utils/data-registry-events.ts @@ -1,6 +1,9 @@ import { Address, ethereum } from "@graphprotocol/graph-ts"; import { newMockEvent } from "matchstick-as/assembly/index"; -import { FileAdded as FileAddedEvent } from "../../../../../generated/DataRegistryImplementationV1/DataRegistryImplementationV1"; +import { + FileAdded as FileAddedEvent, + ProofAdded as ProofAddedEvent +} from "../../../../../generated/DataRegistryImplementationV1/DataRegistryImplementationV1"; export function createFileAddedEvent( fileId: i32, @@ -26,3 +29,20 @@ export function createFileAddedEvent( return fileAddedEvent; } + +export function createProofAddedEvent( + fileId: i32, + proofIndex: i32, +): ProofAddedEvent { + const proofAddedEvent = changetype(newMockEvent()); + proofAddedEvent.parameters = new Array(); + + proofAddedEvent.parameters.push( + new ethereum.EventParam("fileId", ethereum.Value.fromI32(fileId)), + ); + proofAddedEvent.parameters.push( + new ethereum.EventParam("proofIndex", ethereum.Value.fromI32(proofIndex)), + ); + + return proofAddedEvent; +} diff --git a/tests/unit/contract/v2/data-registry.test.ts b/tests/unit/contract/v2/data-registry.test.ts index 13d234b..1ce66e2 100644 --- a/tests/unit/contract/v2/data-registry.test.ts +++ b/tests/unit/contract/v2/data-registry.test.ts @@ -22,10 +22,10 @@ import { createNewUser, } from "../utils"; import { EPOCH_REFERENCE_ID_CURRENT } from "../../../../src/lib/entity/epoch"; -import { createNewFileOwner } from "../utils/file-owner"; +import { createNewFile } from "../utils/file-owner"; import { createNewUserTotals } from "../utils/user-totals"; import { - getTotalsIdDlp, + getTotalsDlpId, TOTALS_ID_GLOBAL, } from "../../../../src/lib/entity/totals"; import { @@ -43,7 +43,7 @@ describe("handleDataRegistryProofAddedV2", () => { createNewEpoch("1"); createNewEpochReference(EPOCH_REFERENCE_ID_CURRENT, "1"); createNewDlp("1", user.id, "dlp-1"); - createNewFileOwner("1", "0x334e8bbf9c7822fc3f66b11cb0d8ef84c5a4b5ce"); + createNewFile("1", "0x334e8bbf9c7822fc3f66b11cb0d8ef84c5a4b5ce", "ipfs://test"); const proofEvent = createProofAddedEvent( 1, // fileId @@ -94,7 +94,7 @@ describe("handleDataRegistryProofAddedV2", () => { assert.fieldEquals("Totals", totalsId0, "totalFileContributions", "1"); assert.fieldEquals("Totals", totalsId0, "uniqueFileContributors", "1"); - const totalsId1 = getTotalsIdDlp("1"); + const totalsId1 = getTotalsDlpId("1"); assert.fieldEquals("Totals", totalsId1, "totalFileContributions", "1"); assert.fieldEquals("Totals", totalsId1, "uniqueFileContributors", "1"); @@ -127,14 +127,14 @@ describe("handleDataRegistryProofAddedV2", () => { createNewEpoch("1"); createNewEpochReference(EPOCH_REFERENCE_ID_CURRENT, "1"); createNewDlp("1", user.id, "dlp-1"); - createNewFileOwner("1", "0x334e8bbf9c7822fc3f66b11cb0d8ef84c5a4b5ce"); + createNewFile("1", "0x334e8bbf9c7822fc3f66b11cb0d8ef84c5a4b5ce", "ipfs://test"); const globalTotals = createNewTotals(TOTALS_ID_GLOBAL); globalTotals.totalFileContributions = GraphBigInt.fromString("5"); globalTotals.uniqueFileContributors = GraphBigInt.fromString("3"); globalTotals.save(); - const dlpTotalsId = getTotalsIdDlp("1"); + const dlpTotalsId = getTotalsDlpId("1"); const dlpTotals = createNewTotals(dlpTotalsId); dlpTotals.totalFileContributions = GraphBigInt.fromString("2"); dlpTotals.uniqueFileContributors = GraphBigInt.fromString("1"); @@ -204,7 +204,7 @@ describe("handleDataRegistryProofAddedV2", () => { assert.fieldEquals("Totals", totalsId0, "totalFileContributions", "6"); assert.fieldEquals("Totals", totalsId0, "uniqueFileContributors", "3"); - const totalsId1 = getTotalsIdDlp("1"); + const totalsId1 = getTotalsDlpId("1"); assert.fieldEquals("Totals", totalsId1, "totalFileContributions", "3"); assert.fieldEquals("Totals", totalsId1, "uniqueFileContributors", "1"); diff --git a/tests/unit/contract/v3/data-registry.test.ts b/tests/unit/contract/v3/data-registry.test.ts index f49f0e4..7b82557 100644 --- a/tests/unit/contract/v3/data-registry.test.ts +++ b/tests/unit/contract/v3/data-registry.test.ts @@ -22,10 +22,10 @@ import { createNewUser, } from "../utils"; import { EPOCH_REFERENCE_ID_CURRENT } from "../../../../src/lib/entity/epoch"; -import { createNewFileOwner } from "../utils/file-owner"; +import { createNewFile } from "../utils/file-owner"; import { createNewUserTotals } from "../utils/user-totals"; import { - getTotalsIdDlp, + getTotalsDlpId, TOTALS_ID_GLOBAL, } from "../../../../src/lib/entity/totals"; import { @@ -95,7 +95,7 @@ describe("handleDataRegistryProofAddedV3", () => { assert.fieldEquals("Totals", totalsId0, "totalFileContributions", "1"); assert.fieldEquals("Totals", totalsId0, "uniqueFileContributors", "1"); - const totalsId1 = getTotalsIdDlp("1"); + const totalsId1 = getTotalsDlpId("1"); assert.fieldEquals("Totals", totalsId1, "totalFileContributions", "1"); assert.fieldEquals("Totals", totalsId1, "uniqueFileContributors", "1"); @@ -128,14 +128,14 @@ describe("handleDataRegistryProofAddedV3", () => { createNewEpoch("1"); createNewEpochReference(EPOCH_REFERENCE_ID_CURRENT, "1"); createNewDlp("1", user.id, "dlp-1"); - createNewFileOwner("1", "0x334e8bbf9c7822fc3f66b11cb0d8ef84c5a4b5ce"); + createNewFile("1", "0x334e8bbf9c7822fc3f66b11cb0d8ef84c5a4b5ce", "ipfs://test"); const globalTotals = createNewTotals(TOTALS_ID_GLOBAL); globalTotals.totalFileContributions = GraphBigInt.fromString("5"); globalTotals.uniqueFileContributors = GraphBigInt.fromString("3"); globalTotals.save(); - const dlpTotalsId = getTotalsIdDlp("1"); + const dlpTotalsId = getTotalsDlpId("1"); const dlpTotals = createNewTotals(dlpTotalsId); dlpTotals.totalFileContributions = GraphBigInt.fromString("2"); dlpTotals.uniqueFileContributors = GraphBigInt.fromString("1"); @@ -207,7 +207,7 @@ describe("handleDataRegistryProofAddedV3", () => { assert.fieldEquals("Totals", totalsId0, "totalFileContributions", "6"); assert.fieldEquals("Totals", totalsId0, "uniqueFileContributors", "3"); - const totalsId1 = getTotalsIdDlp("1"); + const totalsId1 = getTotalsDlpId("1"); assert.fieldEquals("Totals", totalsId1, "totalFileContributions", "3"); assert.fieldEquals("Totals", totalsId1, "uniqueFileContributors", "1"); diff --git a/tests/unit/contract/v5/utils/dlp-registry-events.ts b/tests/unit/contract/v5/utils/dlp-registry-events.ts index f7a529e..5ea1c12 100644 --- a/tests/unit/contract/v5/utils/dlp-registry-events.ts +++ b/tests/unit/contract/v5/utils/dlp-registry-events.ts @@ -8,7 +8,6 @@ import { DlpRegistered, DlpUpdated, DlpStatusUpdated, - DlpSubEligibilityThresholdUpdated, DlpVerificationUpdated, DlpTokenUpdated, } from "../../../../../generated/DLPRegistryImplementationV5/DLPRegistryImplementationV5"; @@ -109,23 +108,6 @@ export function createDlpStatusUpdatedEvent( return event; } -export function createDlpEligibilityThresholdUpdatedEvent( - newDlpSubEligibilityThreshold: number, -): DlpSubEligibilityThresholdUpdated { - const event = changetype(newMockEvent()); - - event.parameters = [ - new ethereum.EventParam( - "newDlpSubEligibilityThreshold", - ethereum.Value.fromUnsignedBigInt( - GraphBigInt.fromI32(newDlpSubEligibilityThreshold), - ), - ), - ]; - - return event; -} - export function createDlpVerificationUpdatedEvent( dlpId: number, verified: boolean, diff --git a/tests/unit/integration/refactored-handlers.test.ts b/tests/unit/integration/refactored-handlers.test.ts new file mode 100644 index 0000000..ed79948 --- /dev/null +++ b/tests/unit/integration/refactored-handlers.test.ts @@ -0,0 +1,190 @@ +import { + assert, + beforeEach, + clearStore, + describe, + test, +} from "matchstick-as/assembly/index"; +import { BigInt as GraphBigInt } from "@graphprotocol/graph-ts"; +import { + handleFileAddedV1, + handleDataRegistryProofAddedV1 +} from "../../../src/lib/contract/v1/data-registry"; +import { + handleFileAddedV2, + handleDataRegistryProofAddedV2 +} from "../../../src/lib/contract/v2/data-registry"; +import { + handleFileAddedV3, + handleDataRegistryProofAddedV3 +} from "../../../src/lib/contract/v3/data-registry"; +import { createFileAddedEvent } from "../contract/v1/utils/data-registry-events"; +import { createProofAddedEvent } from "../contract/v1/utils/data-registry-events"; +import { createFileAddedEvent as createFileAddedEventV2 } from "../contract/v2/utils/data-registry-events"; +import { createProofAddedEvent as createProofAddedEventV2 } from "../contract/v2/utils/data-registry-events"; +import { createFileAddedEvent as createFileAddedEventV3 } from "../contract/v3/utils/data-registry-events"; +import { createProofAddedEvent as createProofAddedEventV3 } from "../contract/v3/utils/data-registry-events"; +import { + createNewEpoch, + createNewEpochReference, + createNewDlp, + createNewUser +} from "../contract/utils"; +import { EPOCH_REFERENCE_ID_CURRENT } from "../../../src/lib/entity/epoch"; + +// Hook to clear the store before each test +beforeEach(() => { + clearStore(); +}); + +describe("Integration Tests for Refactored Handlers", () => { + test("V1, V2, and V3 handlers all use shared utilities correctly", () => { + // ARRANGE + const fileId1 = 1; + const fileId2 = 2; + const fileId3 = 3; + const ownerAddress = "0x1234567890123456789012345678901234567890"; + const dlpId = "1"; + const url = "ipfs://QmTest123"; + + // Create required entities + createNewEpoch("1"); + createNewEpochReference(EPOCH_REFERENCE_ID_CURRENT, "1"); + createNewUser(ownerAddress); + createNewDlp(dlpId, ownerAddress, "Test DLP"); + + // Create file events for all versions + const fileEventV1 = createFileAddedEvent(fileId1, ownerAddress, url); + const fileEventV2 = createFileAddedEventV2(fileId2, ownerAddress, url); + const fileEventV3 = createFileAddedEventV3(fileId3, ownerAddress, url); + + // ACT - Handle file events + handleFileAddedV1(fileEventV1); + handleFileAddedV2(fileEventV2); + handleFileAddedV3(fileEventV3); + + // ASSERT - All versions should create File entities with correct schema IDs + assert.entityCount("File", 3); + assert.fieldEquals("File", fileId1.toString(), "schemaId", "0"); // V1 default + assert.fieldEquals("File", fileId2.toString(), "schemaId", "0"); // V2 default + assert.fieldEquals("File", fileId3.toString(), "schemaId", "0"); // V3 default + + // All should have same owner + assert.fieldEquals("File", fileId1.toString(), "owner", ownerAddress); + assert.fieldEquals("File", fileId2.toString(), "owner", ownerAddress); + assert.fieldEquals("File", fileId3.toString(), "owner", ownerAddress); + + // Only one User entity should be created (shared utility) + assert.entityCount("User", 1); + assert.fieldEquals("User", ownerAddress, "id", ownerAddress); + }); + + test("V1, V2, and V3 proof handlers create different proof structures", () => { + // ARRANGE + const fileId1 = 1; + const fileId2 = 2; + const fileId3 = 3; + const ownerAddress = "0x1234567890123456789012345678901234567890"; + const dlpId = "1"; + const url = "ipfs://QmTest123"; + const proofIndex = 0; + + // Create required entities + createNewEpoch("1"); + createNewEpochReference(EPOCH_REFERENCE_ID_CURRENT, "1"); + createNewUser(ownerAddress); + createNewDlp(dlpId, ownerAddress, "Test DLP"); + + // Create files first + const fileEventV1 = createFileAddedEvent(fileId1, ownerAddress, url); + const fileEventV2 = createFileAddedEventV2(fileId2, ownerAddress, url); + const fileEventV3 = createFileAddedEventV3(fileId3, ownerAddress, url); + + handleFileAddedV1(fileEventV1); + handleFileAddedV2(fileEventV2); + handleFileAddedV3(fileEventV3); + + // Create proof events + const proofEventV1 = createProofAddedEvent(fileId1, proofIndex); + const proofEventV2 = createProofAddedEventV2(fileId2, proofIndex, parseInt(dlpId), 100); + const proofEventV3 = createProofAddedEventV3(fileId3, ownerAddress, parseInt(dlpId), proofIndex, 100, "test"); + + // ACT - Handle proof events + handleDataRegistryProofAddedV1(proofEventV1); + handleDataRegistryProofAddedV2(proofEventV2); + handleDataRegistryProofAddedV3(proofEventV3); + + // ASSERT - All versions should create DataRegistryProof entities + assert.entityCount("DataRegistryProof", 3); + + // V1 proof should not have user or DLP + const proofIdV1 = proofEventV1.transaction.hash.toHexString(); + assert.fieldEquals("DataRegistryProof", proofIdV1, "epoch", "1"); + assert.fieldEquals("DataRegistryProof", proofIdV1, "fileId", fileId1.toString()); + + // V2 proof should have DLP but not user + const proofIdV2 = proofEventV2.transaction.hash.toHexString(); + assert.fieldEquals("DataRegistryProof", proofIdV2, "dlp", dlpId); + assert.fieldEquals("DataRegistryProof", proofIdV2, "epoch", "1"); + + // V3 proof should have both user and DLP + const proofIdV3 = proofEventV3.transaction.hash.toHexString(); + assert.fieldEquals("DataRegistryProof", proofIdV3, "user", ownerAddress); + assert.fieldEquals("DataRegistryProof", proofIdV3, "dlp", dlpId); + assert.fieldEquals("DataRegistryProof", proofIdV3, "epoch", "1"); + }); + + test("Totals are updated correctly across all versions", () => { + // ARRANGE + const fileId1 = 1; + const fileId2 = 2; + const fileId3 = 3; + const ownerAddress = "0x1234567890123456789012345678901234567890"; + const dlpId = "1"; + const url = "ipfs://QmTest123"; + const proofIndex = 0; + + // Create required entities + createNewEpoch("1"); + createNewEpochReference(EPOCH_REFERENCE_ID_CURRENT, "1"); + createNewUser(ownerAddress); + createNewDlp(dlpId, ownerAddress, "Test DLP"); + + // Create files + const fileEventV1 = createFileAddedEvent(fileId1, ownerAddress, url); + const fileEventV2 = createFileAddedEventV2(fileId2, ownerAddress, url); + const fileEventV3 = createFileAddedEventV3(fileId3, ownerAddress, url); + + handleFileAddedV1(fileEventV1); + handleFileAddedV2(fileEventV2); + handleFileAddedV3(fileEventV3); + + // Create proof events + const proofEventV1 = createProofAddedEvent(fileId1, proofIndex); + const proofEventV2 = createProofAddedEventV2(fileId2, proofIndex, parseInt(dlpId), 100); + const proofEventV3 = createProofAddedEventV3(fileId3, ownerAddress, parseInt(dlpId), proofIndex, 100, "test"); + + // ACT - Handle proof events + handleDataRegistryProofAddedV1(proofEventV1); + handleDataRegistryProofAddedV2(proofEventV2); + handleDataRegistryProofAddedV3(proofEventV3); + + // ASSERT - Check global totals + assert.entityCount("Totals", 2); // Global + DLP totals + assert.fieldEquals("Totals", "global", "totalFileContributions", "3"); + assert.fieldEquals("Totals", "global", "uniqueFileContributors", "1"); // Same user + + // Check DLP totals (V2 and V3 should contribute) + const dlpTotalsId = `dlp-${dlpId}`; + assert.fieldEquals("Totals", dlpTotalsId, "totalFileContributions", "2"); + assert.fieldEquals("Totals", dlpTotalsId, "uniqueFileContributors", "1"); + + // Check user totals + const userTotalsId = `user-${ownerAddress}`; + assert.fieldEquals("UserTotals", userTotalsId, "fileContributionsCount", "3"); + + // Check DLP user totals + const dlpUserTotalsId = `user-${ownerAddress}-dlp-${dlpId}`; + assert.fieldEquals("UserTotals", dlpUserTotalsId, "fileContributionsCount", "2"); + }); +}); \ No newline at end of file diff --git a/tests/unit/lib/contract/shared/constants.test.ts b/tests/unit/lib/contract/shared/constants.test.ts new file mode 100644 index 0000000..c467901 --- /dev/null +++ b/tests/unit/lib/contract/shared/constants.test.ts @@ -0,0 +1,40 @@ +import { + assert, + describe, + test, +} from "matchstick-as/assembly/index"; +import { BigInt as GraphBigInt } from "@graphprotocol/graph-ts"; +import { + ONE, + ZERO, + ERROR_NO_EPOCH, + ERROR_DLP_NOT_FOUND, + ERROR_NO_FILE_OWNER, + DEFAULT_SCHEMA_ID +} from "../../../../../src/lib/contract/shared/constants"; + +describe("Shared Constants", () => { + test("BigInt constants are correct", () => { + // ASSERT + assert.bigIntEquals(ONE, GraphBigInt.fromI32(1)); + assert.bigIntEquals(ZERO, GraphBigInt.fromI32(0)); + assert.bigIntEquals(DEFAULT_SCHEMA_ID, ZERO); + }); + + test("Error message constants are defined", () => { + // ASSERT + assert.stringEquals(ERROR_NO_EPOCH, "No epoch found for block"); + assert.stringEquals(ERROR_DLP_NOT_FOUND, "DLP not found for proof"); + assert.stringEquals(ERROR_NO_FILE_OWNER, "Cannot update totals: file not found or has no owner"); + }); + + test("Constants are usable in computations", () => { + // ARRANGE & ACT + const result = ONE.plus(ZERO); + const doubled = ONE.times(GraphBigInt.fromI32(2)); + + // ASSERT + assert.bigIntEquals(result, GraphBigInt.fromI32(1)); + assert.bigIntEquals(doubled, GraphBigInt.fromI32(2)); + }); +}); \ No newline at end of file diff --git a/tests/unit/lib/contract/shared/event-utils.test.ts b/tests/unit/lib/contract/shared/event-utils.test.ts new file mode 100644 index 0000000..ca9506c --- /dev/null +++ b/tests/unit/lib/contract/shared/event-utils.test.ts @@ -0,0 +1,160 @@ +import { + assert, + beforeEach, + clearStore, + describe, + test, +} from "matchstick-as/assembly/index"; +import { BigInt as GraphBigInt, ethereum } from "@graphprotocol/graph-ts"; +import { newMockEvent } from "matchstick-as/assembly/index"; +import { + logEventWithTxHash, + logEntityNotFound, + setBlockchainMetadata, + createCompositeId, + createTransactionId +} from "../../../../../src/lib/contract/shared/event-utils"; + +// Hook to clear the store before each test +beforeEach(() => { + clearStore(); +}); + +describe("logEventWithTxHash", () => { + test("logs event without throwing", () => { + // ARRANGE + const eventName = "TestEvent"; + const transactionHash = "0xabcd1234"; + + // ACT - this should not throw + logEventWithTxHash(eventName, transactionHash); + + // ASSERT - if we reach here, the function didn't throw + assert.assertTrue(true); + }); +}); + +describe("logEntityNotFound", () => { + test("logs entity not found without throwing", () => { + // ARRANGE + const entityType = "TestEntity"; + const entityId = "123"; + + // ACT - this should not throw + logEntityNotFound(entityType, entityId); + + // ASSERT - if we reach here, the function didn't throw + assert.assertTrue(true); + }); + + test("logs entity not found with context without throwing", () => { + // ARRANGE + const entityType = "TestEntity"; + const entityId = "456"; + const context = "test operation"; + + // ACT - this should not throw + logEntityNotFound(entityType, entityId, context); + + // ASSERT - if we reach here, the function didn't throw + assert.assertTrue(true); + }); +}); + +describe("setBlockchainMetadata", () => { + test("sets blockchain metadata on entity", () => { + // ARRANGE + const mockEvent = newMockEvent(); + const mockBlock = mockEvent.block; + const mockTransaction = mockEvent.transaction; + const logIndex = GraphBigInt.fromI32(5); + + // Create a simple entity-like object + const entity = new Map(); + + // ACT + setBlockchainMetadata(entity, mockBlock, mockTransaction, logIndex); + + // ASSERT + // Note: In a real scenario, we'd test this with an actual entity + // but this tests that the function doesn't throw + assert.assertTrue(true); + }); + + test("sets blockchain metadata without log index", () => { + // ARRANGE + const mockEvent = newMockEvent(); + const mockBlock = mockEvent.block; + const mockTransaction = mockEvent.transaction; + + const entity = new Map(); + + // ACT + setBlockchainMetadata(entity, mockBlock, mockTransaction); + + // ASSERT + assert.assertTrue(true); + }); +}); + +describe("createCompositeId", () => { + test("creates composite ID with default separator", () => { + // ARRANGE + const parts = ["user", "123", "dlp", "456"]; + + // ACT + const id = createCompositeId(parts); + + // ASSERT + assert.stringEquals(id, "user-123-dlp-456"); + }); + + test("creates composite ID with custom separator", () => { + // ARRANGE + const parts = ["prefix", "middle", "suffix"]; + const separator = "_"; + + // ACT + const id = createCompositeId(parts, separator); + + // ASSERT + assert.stringEquals(id, "prefix_middle_suffix"); + }); + + test("creates composite ID with single part", () => { + // ARRANGE + const parts = ["single"]; + + // ACT + const id = createCompositeId(parts); + + // ASSERT + assert.stringEquals(id, "single"); + }); +}); + +describe("createTransactionId", () => { + test("creates transaction-based ID", () => { + // ARRANGE + const transactionHash = "0xabcd1234567890"; + const logIndex = GraphBigInt.fromI32(42); + + // ACT + const id = createTransactionId(transactionHash, logIndex); + + // ASSERT + assert.stringEquals(id, "0xabcd1234567890-42"); + }); + + test("creates transaction-based ID with zero log index", () => { + // ARRANGE + const transactionHash = "0xdef456789abc"; + const logIndex = GraphBigInt.fromI32(0); + + // ACT + const id = createTransactionId(transactionHash, logIndex); + + // ASSERT + assert.stringEquals(id, "0xdef456789abc-0"); + }); +}); \ No newline at end of file diff --git a/tests/unit/lib/contract/shared/file-handlers.test.ts b/tests/unit/lib/contract/shared/file-handlers.test.ts new file mode 100644 index 0000000..5cefc4b --- /dev/null +++ b/tests/unit/lib/contract/shared/file-handlers.test.ts @@ -0,0 +1,95 @@ +import { + assert, + beforeEach, + clearStore, + describe, + test, +} from "matchstick-as/assembly/index"; +import { BigInt as GraphBigInt, ethereum, Address, Bytes } from "@graphprotocol/graph-ts"; +import { newMockEvent } from "matchstick-as/assembly/index"; +import { createFileFromEvent, logDataRegistryEvent } from "../../../../../src/lib/contract/shared/file-handlers"; + +// Hook to clear the store before each test +beforeEach(() => { + clearStore(); +}); + +describe("createFileFromEvent", () => { + test("creates a File entity with all required fields", () => { + // ARRANGE + const fileId = "123"; + const ownerAddress = "0x1234567890123456789012345678901234567890"; + const url = "ipfs://QmTest123"; + const schemaId = GraphBigInt.fromI32(42); + + // Create mock block and transaction + const mockEvent = newMockEvent(); + const mockBlock = mockEvent.block; + const mockTransaction = mockEvent.transaction; + + // ACT + const file = createFileFromEvent( + fileId, + ownerAddress, + url, + mockBlock, + mockTransaction, + schemaId + ); + + // ASSERT + assert.entityCount("File", 1); + assert.fieldEquals("File", fileId, "id", fileId); + assert.fieldEquals("File", fileId, "owner", ownerAddress); + assert.fieldEquals("File", fileId, "url", url); + assert.fieldEquals("File", fileId, "schemaId", schemaId.toString()); + assert.fieldEquals("File", fileId, "addedAtBlock", mockBlock.number.toString()); + assert.fieldEquals("File", fileId, "addedAtTimestamp", mockBlock.timestamp.toString()); + assert.fieldEquals("File", fileId, "transactionHash", mockTransaction.hash.toHexString()); + + // Check that User entity was created + assert.entityCount("User", 1); + assert.fieldEquals("User", ownerAddress, "id", ownerAddress); + }); + + test("creates a File entity with default schema ID", () => { + // ARRANGE + const fileId = "456"; + const ownerAddress = "0x2345678901234567890123456789012345678901"; + const url = "ipfs://QmTest456"; + + const mockEvent = newMockEvent(); + const mockBlock = mockEvent.block; + const mockTransaction = mockEvent.transaction; + + // ACT - don't provide schemaId, should use default + const file = createFileFromEvent( + fileId, + ownerAddress, + url, + mockBlock, + mockTransaction + ); + + // ASSERT + assert.entityCount("File", 1); + assert.fieldEquals("File", fileId, "schemaId", "0"); // Default should be 0 + }); +}); + +describe("logDataRegistryEvent", () => { + test("logs event without throwing", () => { + // This test ensures the logging function doesn't throw errors + // In matchstick, we can't directly test log output, but we can ensure it doesn't crash + + // ARRANGE + const eventName = "FileAdded"; + const transactionHash = "0xabcd1234"; + + // ACT - this should not throw + logDataRegistryEvent(eventName, transactionHash); + + // ASSERT - if we reach here, the function didn't throw + assert.assertTrue(true); + }); +}); \ No newline at end of file diff --git a/tests/unit/lib/contract/shared/proof-handlers.test.ts b/tests/unit/lib/contract/shared/proof-handlers.test.ts new file mode 100644 index 0000000..52561d1 --- /dev/null +++ b/tests/unit/lib/contract/shared/proof-handlers.test.ts @@ -0,0 +1,109 @@ +import { + assert, + beforeEach, + clearStore, + describe, + test, +} from "matchstick-as/assembly/index"; +import { BigInt as GraphBigInt, ethereum, Address, Bytes } from "@graphprotocol/graph-ts"; +import { newMockEvent } from "matchstick-as/assembly/index"; +import { createDataRegistryProof } from "../../../../../src/lib/contract/shared/proof-handlers"; + +// Hook to clear the store before each test +beforeEach(() => { + clearStore(); +}); + +describe("createDataRegistryProof", () => { + test("creates a DataRegistryProof entity with all required fields", () => { + // ARRANGE + const transactionHash = "0xabcd1234567890abcd1234567890abcd12345678"; + const epochId = "epoch-1"; + const fileId = GraphBigInt.fromI32(123); + const proofIndex = GraphBigInt.fromI32(456); + + const mockEvent = newMockEvent(); + const mockBlock = mockEvent.block; + const mockTransaction = mockEvent.transaction; + + // ACT + const proof = createDataRegistryProof( + transactionHash, + epochId, + fileId, + proofIndex, + mockBlock, + mockTransaction + ); + + // ASSERT + assert.entityCount("DataRegistryProof", 1); + assert.fieldEquals("DataRegistryProof", transactionHash, "id", transactionHash); + assert.fieldEquals("DataRegistryProof", transactionHash, "epoch", epochId); + assert.fieldEquals("DataRegistryProof", transactionHash, "fileId", fileId.toString()); + assert.fieldEquals("DataRegistryProof", transactionHash, "proofIndex", proofIndex.toString()); + assert.fieldEquals("DataRegistryProof", transactionHash, "createdAt", mockBlock.timestamp.toString()); + assert.fieldEquals("DataRegistryProof", transactionHash, "createdAtBlock", mockBlock.number.toString()); + assert.fieldEquals("DataRegistryProof", transactionHash, "createdTxHash", mockTransaction.hash.toHexString()); + }); + + test("creates a DataRegistryProof entity with optional user and DLP", () => { + // ARRANGE + const transactionHash = "0xdef456789abcdef456789abcdef456789abcdef45"; + const epochId = "epoch-2"; + const fileId = GraphBigInt.fromI32(789); + const proofIndex = GraphBigInt.fromI32(101); + const userId = "0x1234567890123456789012345678901234567890"; + const dlpId = "dlp-123"; + + const mockEvent = newMockEvent(); + const mockBlock = mockEvent.block; + const mockTransaction = mockEvent.transaction; + + // ACT + const proof = createDataRegistryProof( + transactionHash, + epochId, + fileId, + proofIndex, + mockBlock, + mockTransaction, + userId, + dlpId + ); + + // ASSERT + assert.entityCount("DataRegistryProof", 1); + assert.fieldEquals("DataRegistryProof", transactionHash, "user", userId); + assert.fieldEquals("DataRegistryProof", transactionHash, "dlp", dlpId); + }); + + test("creates a DataRegistryProof entity with null optional fields", () => { + // ARRANGE + const transactionHash = "0x987654321098765432109876543210987654321"; + const epochId = "epoch-3"; + const fileId = GraphBigInt.fromI32(999); + const proofIndex = GraphBigInt.fromI32(888); + + const mockEvent = newMockEvent(); + const mockBlock = mockEvent.block; + const mockTransaction = mockEvent.transaction; + + // ACT + const proof = createDataRegistryProof( + transactionHash, + epochId, + fileId, + proofIndex, + mockBlock, + mockTransaction, + null, + null + ); + + // ASSERT + assert.entityCount("DataRegistryProof", 1); + assert.fieldEquals("DataRegistryProof", transactionHash, "id", transactionHash); + // Optional fields should not be set when null is passed + }); +}); \ No newline at end of file diff --git a/tests/unit/lib/contract/shared/totals-updater.test.ts b/tests/unit/lib/contract/shared/totals-updater.test.ts new file mode 100644 index 0000000..46b849b --- /dev/null +++ b/tests/unit/lib/contract/shared/totals-updater.test.ts @@ -0,0 +1,175 @@ +import { + assert, + beforeEach, + clearStore, + describe, + test, +} from "matchstick-as/assembly/index"; +import { BigInt as GraphBigInt } from "@graphprotocol/graph-ts"; +import { + updateGlobalTotals, + updateDlpTotals, + updateAllTotals, + updateTotalsFromFile +} from "../../../../../src/lib/contract/shared/totals-updater"; +import { createNewUser } from "../../../contract/utils/user"; +import { createNewFile } from "../../../contract/utils/file-owner"; +import { createNewTotals } from "../../../contract/utils/totals"; +import { createNewUserTotals } from "../../../contract/utils/user-totals"; +import { + TOTALS_ID_GLOBAL, + getTotalsDlpId +} from "../../../../../src/lib/entity/totals"; +import { + getUserTotalsId, + getUserTotalsIdDlp +} from "../../../../../src/lib/entity/usertotals"; + +// Hook to clear the store before each test +beforeEach(() => { + clearStore(); +}); + +describe("updateGlobalTotals", () => { + test("updates global totals for first-time user", () => { + // ARRANGE + const userId = "0x1234567890123456789012345678901234567890"; + createNewUser(userId); + createNewTotals(TOTALS_ID_GLOBAL); + + // ACT + updateGlobalTotals(userId); + + // ASSERT + // Check user totals + const userTotalsId = getUserTotalsId(userId); + assert.entityCount("UserTotals", 1); + assert.fieldEquals("UserTotals", userTotalsId, "fileContributionsCount", "1"); + + // Check global totals + assert.fieldEquals("Totals", TOTALS_ID_GLOBAL, "totalFileContributions", "1"); + assert.fieldEquals("Totals", TOTALS_ID_GLOBAL, "uniqueFileContributors", "1"); + }); + + test("updates global totals for returning user", () => { + // ARRANGE + const userId = "0x1234567890123456789012345678901234567890"; + createNewUser(userId); + createNewTotals(TOTALS_ID_GLOBAL); + + // Create existing user totals with 2 contributions + const userTotalsId = getUserTotalsId(userId); + const userTotals = createNewUserTotals(userTotalsId); + userTotals.fileContributionsCount = GraphBigInt.fromI32(2); + userTotals.save(); + + // ACT + updateGlobalTotals(userId); + + // ASSERT + // Check user totals incremented + assert.fieldEquals("UserTotals", userTotalsId, "fileContributionsCount", "3"); + + // Check global totals - should increment total but not unique contributors + assert.fieldEquals("Totals", TOTALS_ID_GLOBAL, "totalFileContributions", "1"); + assert.fieldEquals("Totals", TOTALS_ID_GLOBAL, "uniqueFileContributors", "0"); + }); +}); + +describe("updateDlpTotals", () => { + test("updates DLP totals for first-time user", () => { + // ARRANGE + const userId = "0x1234567890123456789012345678901234567890"; + const dlpId = "dlp-123"; + createNewUser(userId); + + const dlpTotalsId = getTotalsDlpId(dlpId); + createNewTotals(dlpTotalsId); + + // ACT + updateDlpTotals(userId, dlpId); + + // ASSERT + // Check DLP user totals + const dlpUserTotalsId = getUserTotalsIdDlp(userId, dlpId); + assert.entityCount("UserTotals", 1); + assert.fieldEquals("UserTotals", dlpUserTotalsId, "fileContributionsCount", "1"); + + // Check DLP totals + assert.fieldEquals("Totals", dlpTotalsId, "totalFileContributions", "1"); + assert.fieldEquals("Totals", dlpTotalsId, "uniqueFileContributors", "1"); + }); +}); + +describe("updateAllTotals", () => { + test("updates both global and DLP totals when DLP provided", () => { + // ARRANGE + const userId = "0x1234567890123456789012345678901234567890"; + const dlpId = "dlp-456"; + createNewUser(userId); + createNewTotals(TOTALS_ID_GLOBAL); + createNewTotals(getTotalsDlpId(dlpId)); + + // ACT + updateAllTotals(userId, dlpId); + + // ASSERT + // Check global totals + assert.fieldEquals("Totals", TOTALS_ID_GLOBAL, "totalFileContributions", "1"); + assert.fieldEquals("Totals", TOTALS_ID_GLOBAL, "uniqueFileContributors", "1"); + + // Check DLP totals + const dlpTotalsId = getTotalsDlpId(dlpId); + assert.fieldEquals("Totals", dlpTotalsId, "totalFileContributions", "1"); + assert.fieldEquals("Totals", dlpTotalsId, "uniqueFileContributors", "1"); + }); + + test("updates only global totals when no DLP provided", () => { + // ARRANGE + const userId = "0x1234567890123456789012345678901234567890"; + createNewUser(userId); + createNewTotals(TOTALS_ID_GLOBAL); + + // ACT + updateAllTotals(userId, null); + + // ASSERT + // Check global totals + assert.fieldEquals("Totals", TOTALS_ID_GLOBAL, "totalFileContributions", "1"); + assert.fieldEquals("Totals", TOTALS_ID_GLOBAL, "uniqueFileContributors", "1"); + + // Should not create any DLP totals + assert.entityCount("Totals", 1); // Only global totals + }); +}); + +describe("updateTotalsFromFile", () => { + test("updates totals based on file owner", () => { + // ARRANGE + const fileId = "123"; + const userId = "0x1234567890123456789012345678901234567890"; + createNewUser(userId); + createNewFile(fileId, userId, "ipfs://test"); + createNewTotals(TOTALS_ID_GLOBAL); + + // ACT + updateTotalsFromFile(fileId, null); + + // ASSERT + assert.fieldEquals("Totals", TOTALS_ID_GLOBAL, "totalFileContributions", "1"); + assert.fieldEquals("Totals", TOTALS_ID_GLOBAL, "uniqueFileContributors", "1"); + }); + + test("handles non-existent file gracefully", () => { + // ARRANGE + const fileId = "999"; + createNewTotals(TOTALS_ID_GLOBAL); + + // ACT - should not throw + updateTotalsFromFile(fileId, null); + + // ASSERT - totals should remain unchanged + assert.fieldEquals("Totals", TOTALS_ID_GLOBAL, "totalFileContributions", "0"); + assert.fieldEquals("Totals", TOTALS_ID_GLOBAL, "uniqueFileContributors", "0"); + }); +}); \ No newline at end of file From e25b62618f6b69efb6a1e085bca0153dfd3ecdf3 Mon Sep 17 00:00:00 2001 From: Eduard Dumea Date: Sat, 19 Jul 2025 00:43:18 +0300 Subject: [PATCH 19/22] added DataPortability events --- abis/v5/DataRegistryImplementation.json | 1188 --------------- ...DataPortabilityGranteesImplementation.json | 858 +++++++++++ ...aPortabilityPermissionsImplementation.json | 1307 +++++++++++++++++ .../DataPortabilityServersImplementation.json | 1303 ++++++++++++++++ config/moksha.json | 7 +- config/vana.json | 7 +- schema.graphql | 52 +- src/lib/contract/v5/data-permission.ts | 115 -- .../contract/v6/data-portability-grantees.ts | 32 + .../v6/data-portability-permissions.ts | 98 ++ .../contract/v6/data-portability-servers.ts | 104 ++ src/lib/contract/v6/index.ts | 15 + src/mapping.ts.template | 11 + subgraph.moksha.yaml | 77 +- subgraph.vana-moksha.yaml | 75 + subgraph.vana.yaml | 75 + 16 files changed, 3984 insertions(+), 1340 deletions(-) delete mode 100644 abis/v5/DataRegistryImplementation.json create mode 100644 abis/v6/DataPortabilityGranteesImplementation.json create mode 100644 abis/v6/DataPortabilityPermissionsImplementation.json create mode 100644 abis/v6/DataPortabilityServersImplementation.json delete mode 100644 src/lib/contract/v5/data-permission.ts create mode 100644 src/lib/contract/v6/data-portability-grantees.ts create mode 100644 src/lib/contract/v6/data-portability-permissions.ts create mode 100644 src/lib/contract/v6/data-portability-servers.ts create mode 100644 src/lib/contract/v6/index.ts diff --git a/abis/v5/DataRegistryImplementation.json b/abis/v5/DataRegistryImplementation.json deleted file mode 100644 index b93e6d8..0000000 --- a/abis/v5/DataRegistryImplementation.json +++ /dev/null @@ -1,1188 +0,0 @@ -[ - { - "inputs": [], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "AccessControlBadConfirmation", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "internalType": "bytes32", - "name": "neededRole", - "type": "bytes32" - } - ], - "name": "AccessControlUnauthorizedAccount", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "target", - "type": "address" - } - ], - "name": "AddressEmptyCode", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "implementation", - "type": "address" - } - ], - "name": "ERC1967InvalidImplementation", - "type": "error" - }, - { - "inputs": [], - "name": "ERC1967NonPayable", - "type": "error" - }, - { - "inputs": [], - "name": "EnforcedPause", - "type": "error" - }, - { - "inputs": [], - "name": "ExpectedPause", - "type": "error" - }, - { - "inputs": [], - "name": "FailedInnerCall", - "type": "error" - }, - { - "inputs": [], - "name": "FileNotFound", - "type": "error" - }, - { - "inputs": [], - "name": "FileUrlAlreadyUsed", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidInitialization", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "schemaId", - "type": "uint256" - } - ], - "name": "InvalidSchemaId", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidUrl", - "type": "error" - }, - { - "inputs": [], - "name": "NoPermission", - "type": "error" - }, - { - "inputs": [], - "name": "NotFileOwner", - "type": "error" - }, - { - "inputs": [], - "name": "NotInitializing", - "type": "error" - }, - { - "inputs": [], - "name": "UUPSUnauthorizedCallContext", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "slot", - "type": "bytes32" - } - ], - "name": "UUPSUnsupportedProxiableUUID", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "fileId", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "ownerAddress", - "type": "address" - }, - { - "indexed": false, - "internalType": "string", - "name": "url", - "type": "string" - } - ], - "name": "FileAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint64", - "name": "version", - "type": "uint64" - } - ], - "name": "Initialized", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Paused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "fileId", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "PermissionGranted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "fileId", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "ownerAddress", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "proofIndex", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "dlpId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "score", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "string", - "name": "proofUrl", - "type": "string" - } - ], - "name": "ProofAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "fileId", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "refinerId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "string", - "name": "url", - "type": "string" - } - ], - "name": "RefinementAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "fileId", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "refinerId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "string", - "name": "url", - "type": "string" - } - ], - "name": "RefinementUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "bytes32", - "name": "previousAdminRole", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "bytes32", - "name": "newAdminRole", - "type": "bytes32" - } - ], - "name": "RoleAdminChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "RoleGranted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "RoleRevoked", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Unpaused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "implementation", - "type": "address" - } - ], - "name": "Upgraded", - "type": "event" - }, - { - "inputs": [], - "name": "DEFAULT_ADMIN_ROLE", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "MAINTAINER_ROLE", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "REFINEMENT_SERVICE_ROLE", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "UPGRADE_INTERFACE_VERSION", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "url", - "type": "string" - } - ], - "name": "addFile", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "fileId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "internalType": "string", - "name": "key", - "type": "string" - } - ], - "name": "addFilePermission", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "url", - "type": "string" - }, - { - "internalType": "address", - "name": "ownerAddress", - "type": "address" - }, - { - "components": [ - { - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "internalType": "string", - "name": "key", - "type": "string" - } - ], - "internalType": "struct IDataRegistry.Permission[]", - "name": "permissions", - "type": "tuple[]" - } - ], - "name": "addFileWithPermissions", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "url", - "type": "string" - }, - { - "internalType": "address", - "name": "ownerAddress", - "type": "address" - }, - { - "components": [ - { - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "internalType": "string", - "name": "key", - "type": "string" - } - ], - "internalType": "struct IDataRegistry.Permission[]", - "name": "permissions", - "type": "tuple[]" - }, - { - "internalType": "uint256", - "name": "schemaId", - "type": "uint256" - } - ], - "name": "addFileWithPermissionsAndSchema", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "url", - "type": "string" - }, - { - "internalType": "uint256", - "name": "schemaId", - "type": "uint256" - } - ], - "name": "addFileWithSchema", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "fileId", - "type": "uint256" - }, - { - "components": [ - { - "internalType": "bytes", - "name": "signature", - "type": "bytes" - }, - { - "components": [ - { - "internalType": "uint256", - "name": "score", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "dlpId", - "type": "uint256" - }, - { - "internalType": "string", - "name": "metadata", - "type": "string" - }, - { - "internalType": "string", - "name": "proofUrl", - "type": "string" - }, - { - "internalType": "string", - "name": "instruction", - "type": "string" - } - ], - "internalType": "struct IDataRegistry.ProofData", - "name": "data", - "type": "tuple" - } - ], - "internalType": "struct IDataRegistry.Proof", - "name": "proof", - "type": "tuple" - } - ], - "name": "addProof", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "fileId", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "refinerId", - "type": "uint256" - }, - { - "internalType": "string", - "name": "url", - "type": "string" - }, - { - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "internalType": "string", - "name": "key", - "type": "string" - } - ], - "name": "addRefinementWithPermission", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "dataRefinerRegistry", - "outputs": [ - { - "internalType": "contract IDataRefinerRegistry", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "url", - "type": "string" - } - ], - "name": "fileIdByUrl", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "fileId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "filePermissions", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "fileId", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "index", - "type": "uint256" - } - ], - "name": "fileProofs", - "outputs": [ - { - "components": [ - { - "internalType": "bytes", - "name": "signature", - "type": "bytes" - }, - { - "components": [ - { - "internalType": "uint256", - "name": "score", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "dlpId", - "type": "uint256" - }, - { - "internalType": "string", - "name": "metadata", - "type": "string" - }, - { - "internalType": "string", - "name": "proofUrl", - "type": "string" - }, - { - "internalType": "string", - "name": "instruction", - "type": "string" - } - ], - "internalType": "struct IDataRegistry.ProofData", - "name": "data", - "type": "tuple" - } - ], - "internalType": "struct IDataRegistry.Proof", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "fileId", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "refinerId", - "type": "uint256" - } - ], - "name": "fileRefinements", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "fileId", - "type": "uint256" - } - ], - "name": "files", - "outputs": [ - { - "components": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "address", - "name": "ownerAddress", - "type": "address" - }, - { - "internalType": "string", - "name": "url", - "type": "string" - }, - { - "internalType": "uint256", - "name": "addedAtBlock", - "type": "uint256" - } - ], - "internalType": "struct IDataRegistry.FileResponse", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "filesCount", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - } - ], - "name": "getRoleAdmin", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "grantRole", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "hasRole", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "trustedForwarderAddress", - "type": "address" - }, - { - "internalType": "address", - "name": "ownerAddress", - "type": "address" - } - ], - "name": "initialize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "forwarder", - "type": "address" - } - ], - "name": "isTrustedForwarder", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes[]", - "name": "data", - "type": "bytes[]" - } - ], - "name": "multicall", - "outputs": [ - { - "internalType": "bytes[]", - "name": "results", - "type": "bytes[]" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "pause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "paused", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "proxiableUUID", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "callerConfirmation", - "type": "address" - } - ], - "name": "renounceRole", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "revokeRole", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "adminRole", - "type": "bytes32" - } - ], - "name": "setRoleAdmin", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes4", - "name": "interfaceId", - "type": "bytes4" - } - ], - "name": "supportsInterface", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "trustedForwarder", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "unpause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "contract IDataRefinerRegistry", - "name": "newDataRefinerRegistry", - "type": "address" - } - ], - "name": "updateDataRefinerRegistry", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "trustedForwarderAddress", - "type": "address" - } - ], - "name": "updateTrustedForwarder", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "newImplementation", - "type": "address" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "upgradeToAndCall", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [], - "name": "version", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - } -] \ No newline at end of file diff --git a/abis/v6/DataPortabilityGranteesImplementation.json b/abis/v6/DataPortabilityGranteesImplementation.json new file mode 100644 index 0000000..9222943 --- /dev/null +++ b/abis/v6/DataPortabilityGranteesImplementation.json @@ -0,0 +1,858 @@ +[ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "AccessControlBadConfirmation", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "neededRole", + "type": "bytes32" + } + ], + "name": "AccessControlUnauthorizedAccount", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + } + ], + "name": "AddressEmptyCode", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "ERC1967InvalidImplementation", + "type": "error" + }, + { + "inputs": [], + "name": "ERC1967NonPayable", + "type": "error" + }, + { + "inputs": [], + "name": "EmptyPublicKey", + "type": "error" + }, + { + "inputs": [], + "name": "EnforcedPause", + "type": "error" + }, + { + "inputs": [], + "name": "ExpectedPause", + "type": "error" + }, + { + "inputs": [], + "name": "FailedInnerCall", + "type": "error" + }, + { + "inputs": [], + "name": "GranteeAlreadyRegistered", + "type": "error" + }, + { + "inputs": [], + "name": "GranteeNotFound", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidInitialization", + "type": "error" + }, + { + "inputs": [], + "name": "NotInitializing", + "type": "error" + }, + { + "inputs": [], + "name": "UUPSUnauthorizedCallContext", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "slot", + "type": "bytes32" + } + ], + "name": "UUPSUnsupportedProxiableUUID", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddress", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "granteeId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "granteeAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "string", + "name": "publicKey", + "type": "string" + } + ], + "name": "GranteeRegistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint64", + "name": "version", + "type": "uint64" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "previousAdminRole", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "newAdminRole", + "type": "bytes32" + } + ], + "name": "RoleAdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "inputs": [], + "name": "DEFAULT_ADMIN_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAINTAINER_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "PERMISSION_MANAGER_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "UPGRADE_INTERFACE_VERSION", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "granteeId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "permissionId", + "type": "uint256" + } + ], + "name": "addPermissionToGrantee", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleAdmin", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "granteeId", + "type": "uint256" + } + ], + "name": "grantee", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "granteeAddress", + "type": "address" + }, + { + "internalType": "string", + "name": "publicKey", + "type": "string" + }, + { + "internalType": "uint256[]", + "name": "permissionIds", + "type": "uint256[]" + } + ], + "internalType": "struct IDataPortabilityGrantees.GranteeInfo", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "granteeAddress", + "type": "address" + } + ], + "name": "granteeAddressToId", + "outputs": [ + { + "internalType": "uint256", + "name": "granteeId", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "granteeAddress", + "type": "address" + } + ], + "name": "granteeByAddress", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "granteeAddress", + "type": "address" + }, + { + "internalType": "string", + "name": "publicKey", + "type": "string" + }, + { + "internalType": "uint256[]", + "name": "permissionIds", + "type": "uint256[]" + } + ], + "internalType": "struct IDataPortabilityGrantees.GranteeInfo", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "granteeId", + "type": "uint256" + } + ], + "name": "granteeInfo", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "granteeAddress", + "type": "address" + }, + { + "internalType": "string", + "name": "publicKey", + "type": "string" + }, + { + "internalType": "uint256[]", + "name": "permissionIds", + "type": "uint256[]" + } + ], + "internalType": "struct IDataPortabilityGrantees.GranteeInfo", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "granteeId", + "type": "uint256" + } + ], + "name": "granteePermissionIds", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "granteeId", + "type": "uint256" + } + ], + "name": "granteePermissions", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "granteesCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRole", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "trustedForwarderAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "ownerAddress", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "forwarder", + "type": "address" + } + ], + "name": "isTrustedForwarder", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes[]", + "name": "data", + "type": "bytes[]" + } + ], + "name": "multicall", + "outputs": [ + { + "internalType": "bytes[]", + "name": "results", + "type": "bytes[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "paused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proxiableUUID", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "granteeAddress", + "type": "address" + }, + { + "internalType": "string", + "name": "publicKey", + "type": "string" + } + ], + "name": "registerGrantee", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "granteeId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "permissionId", + "type": "uint256" + } + ], + "name": "removePermissionFromGrantee", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "callerConfirmation", + "type": "address" + } + ], + "name": "renounceRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "adminRole", + "type": "bytes32" + } + ], + "name": "setRoleAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "trustedForwarder", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "unpause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "trustedForwarderAddress", + "type": "address" + } + ], + "name": "updateTrustedForwarder", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + } + ] diff --git a/abis/v6/DataPortabilityPermissionsImplementation.json b/abis/v6/DataPortabilityPermissionsImplementation.json new file mode 100644 index 0000000..d60f800 --- /dev/null +++ b/abis/v6/DataPortabilityPermissionsImplementation.json @@ -0,0 +1,1307 @@ +[ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "AccessControlBadConfirmation", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "neededRole", + "type": "bytes32" + } + ], + "name": "AccessControlUnauthorizedAccount", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + } + ], + "name": "AddressEmptyCode", + "type": "error" + }, + { + "inputs": [], + "name": "ECDSAInvalidSignature", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "length", + "type": "uint256" + } + ], + "name": "ECDSAInvalidSignatureLength", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "ECDSAInvalidSignatureS", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "ERC1967InvalidImplementation", + "type": "error" + }, + { + "inputs": [], + "name": "ERC1967NonPayable", + "type": "error" + }, + { + "inputs": [], + "name": "EmptyGrant", + "type": "error" + }, + { + "inputs": [], + "name": "EnforcedPause", + "type": "error" + }, + { + "inputs": [], + "name": "ExpectedPause", + "type": "error" + }, + { + "inputs": [], + "name": "FailedInnerCall", + "type": "error" + }, + { + "inputs": [], + "name": "GrantAlreadyUsed", + "type": "error" + }, + { + "inputs": [], + "name": "GranteeNotFound", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "permissionId", + "type": "uint256" + } + ], + "name": "InactivePermission", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidInitialization", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "expectedNonce", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "providedNonce", + "type": "uint256" + } + ], + "name": "InvalidNonce", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidSignature", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "fileOwner", + "type": "address" + }, + { + "internalType": "address", + "name": "requestor", + "type": "address" + } + ], + "name": "NotFileOwner", + "type": "error" + }, + { + "inputs": [], + "name": "NotInitializing", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "permissionOwner", + "type": "address" + }, + { + "internalType": "address", + "name": "requestor", + "type": "address" + } + ], + "name": "NotPermissionGrantor", + "type": "error" + }, + { + "inputs": [], + "name": "UUPSUnauthorizedCallContext", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "slot", + "type": "bytes32" + } + ], + "name": "UUPSUnsupportedProxiableUUID", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddress", + "type": "error" + }, + { + "anonymous": false, + "inputs": [], + "name": "EIP712DomainChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint64", + "name": "version", + "type": "uint64" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "permissionId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "granteeId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "grant", + "type": "string" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "fileIds", + "type": "uint256[]" + } + ], + "name": "PermissionAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "permissionId", + "type": "uint256" + } + ], + "name": "PermissionRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "previousAdminRole", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "newAdminRole", + "type": "bytes32" + } + ], + "name": "RoleAdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "inputs": [], + "name": "DEFAULT_ADMIN_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAINTAINER_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "UPGRADE_INTERFACE_VERSION", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "granteeId", + "type": "uint256" + }, + { + "internalType": "string", + "name": "grant", + "type": "string" + }, + { + "internalType": "uint256[]", + "name": "fileIds", + "type": "uint256[]" + } + ], + "internalType": "struct IDataPortabilityPermissions.PermissionInput", + "name": "permissionInput", + "type": "tuple" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "name": "addPermission", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "dataPortabilityGrantees", + "outputs": [ + { + "internalType": "contract IDataPortabilityGrantees", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "dataPortabilityServers", + "outputs": [ + { + "internalType": "contract IDataPortabilityServers", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "dataRegistry", + "outputs": [ + { + "internalType": "contract IDataRegistry", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "eip712Domain", + "outputs": [ + { + "internalType": "bytes1", + "name": "fields", + "type": "bytes1" + }, + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "version", + "type": "string" + }, + { + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "verifyingContract", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "salt", + "type": "bytes32" + }, + { + "internalType": "uint256[]", + "name": "extensions", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "fileId", + "type": "uint256" + } + ], + "name": "filePermissionIds", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "fileId", + "type": "uint256" + } + ], + "name": "filePermissions", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleAdmin", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "grantHash", + "type": "bytes32" + } + ], + "name": "grantHashToPermissionId", + "outputs": [ + { + "internalType": "uint256", + "name": "permissionId", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRole", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "trustedForwarderAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "ownerAddress", + "type": "address" + }, + { + "internalType": "contract IDataRegistry", + "name": "dataRegistryAddress", + "type": "address" + }, + { + "internalType": "contract IDataPortabilityServers", + "name": "serversContractAddr", + "type": "address" + }, + { + "internalType": "contract IDataPortabilityGrantees", + "name": "granteesContractAddr", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "permissionId", + "type": "uint256" + } + ], + "name": "isActivePermission", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "forwarder", + "type": "address" + } + ], + "name": "isTrustedForwarder", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes[]", + "name": "data", + "type": "bytes[]" + } + ], + "name": "multicall", + "outputs": [ + { + "internalType": "bytes[]", + "name": "results", + "type": "bytes[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "paused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "permissionId", + "type": "uint256" + } + ], + "name": "permission", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "address", + "name": "grantor", + "type": "address" + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "granteeId", + "type": "uint256" + }, + { + "internalType": "string", + "name": "grant", + "type": "string" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "startBlock", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "endBlock", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "fileIds", + "type": "uint256[]" + } + ], + "internalType": "struct IDataPortabilityPermissions.PermissionInfo", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "permissionId", + "type": "uint256" + } + ], + "name": "permissionFileIds", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "grant", + "type": "string" + } + ], + "name": "permissionIdByGrant", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "permissionsCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proxiableUUID", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "callerConfirmation", + "type": "address" + } + ], + "name": "renounceRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "permissionId", + "type": "uint256" + } + ], + "name": "revokePermission", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "permissionId", + "type": "uint256" + } + ], + "internalType": "struct IDataPortabilityPermissions.RevokePermissionInput", + "name": "revokePermissionInput", + "type": "tuple" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "name": "revokePermissionWithSignature", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "adminRole", + "type": "bytes32" + } + ], + "name": "setRoleAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "trustedForwarder", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "unpause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IDataRegistry", + "name": "newDataRegistry", + "type": "address" + } + ], + "name": "updateDataRegistry", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IDataPortabilityGrantees", + "name": "newGranteesContract", + "type": "address" + } + ], + "name": "updateGranteesContract", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IDataPortabilityServers", + "name": "newServersContract", + "type": "address" + } + ], + "name": "updateServersContract", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "trustedForwarderAddress", + "type": "address" + } + ], + "name": "updateTrustedForwarder", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "userAddress", + "type": "address" + } + ], + "name": "user", + "outputs": [ + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "permissionIds", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "revokedPermissionIds", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "userAddress", + "type": "address" + } + ], + "name": "userNonce", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "userAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "permissionIndex", + "type": "uint256" + } + ], + "name": "userPermissionIdsAt", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "userAddress", + "type": "address" + } + ], + "name": "userPermissionIdsLength", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "userAddress", + "type": "address" + } + ], + "name": "userPermissionIdsValues", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "userAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "permissionIndex", + "type": "uint256" + } + ], + "name": "userRevokedPermissionIdsAt", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "userAddress", + "type": "address" + } + ], + "name": "userRevokedPermissionIdsLength", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "userAddress", + "type": "address" + } + ], + "name": "userRevokedPermissionIdsValues", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + } + ] + diff --git a/abis/v6/DataPortabilityServersImplementation.json b/abis/v6/DataPortabilityServersImplementation.json new file mode 100644 index 0000000..1f30af3 --- /dev/null +++ b/abis/v6/DataPortabilityServersImplementation.json @@ -0,0 +1,1303 @@ +[ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "AccessControlBadConfirmation", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "neededRole", + "type": "bytes32" + } + ], + "name": "AccessControlUnauthorizedAccount", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + } + ], + "name": "AddressEmptyCode", + "type": "error" + }, + { + "inputs": [], + "name": "ECDSAInvalidSignature", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "length", + "type": "uint256" + } + ], + "name": "ECDSAInvalidSignatureLength", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "ECDSAInvalidSignatureS", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "ERC1967InvalidImplementation", + "type": "error" + }, + { + "inputs": [], + "name": "ERC1967NonPayable", + "type": "error" + }, + { + "inputs": [], + "name": "EmptyPublicKey", + "type": "error" + }, + { + "inputs": [], + "name": "EmptyUrl", + "type": "error" + }, + { + "inputs": [], + "name": "EnforcedPause", + "type": "error" + }, + { + "inputs": [], + "name": "ExpectedPause", + "type": "error" + }, + { + "inputs": [], + "name": "FailedInnerCall", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidInitialization", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "expectedNonce", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "providedNonce", + "type": "uint256" + } + ], + "name": "InvalidNonce", + "type": "error" + }, + { + "inputs": [], + "name": "NotInitializing", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serverOwner", + "type": "address" + }, + { + "internalType": "address", + "name": "requestor", + "type": "address" + } + ], + "name": "NotServerOwner", + "type": "error" + }, + { + "inputs": [], + "name": "ServerAlreadyRegistered", + "type": "error" + }, + { + "inputs": [], + "name": "ServerAlreadyTrusted", + "type": "error" + }, + { + "inputs": [], + "name": "ServerAlreadyUntrusted", + "type": "error" + }, + { + "inputs": [], + "name": "ServerNotFound", + "type": "error" + }, + { + "inputs": [], + "name": "ServerNotTrusted", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "existingUrl", + "type": "string" + }, + { + "internalType": "string", + "name": "providedUrl", + "type": "string" + } + ], + "name": "ServerUrlMismatch", + "type": "error" + }, + { + "inputs": [], + "name": "UUPSUnauthorizedCallContext", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "slot", + "type": "bytes32" + } + ], + "name": "UUPSUnsupportedProxiableUUID", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddress", + "type": "error" + }, + { + "anonymous": false, + "inputs": [], + "name": "EIP712DomainChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint64", + "name": "version", + "type": "uint64" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "previousAdminRole", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "newAdminRole", + "type": "bytes32" + } + ], + "name": "RoleAdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "serverId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "serverAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "publicKey", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "string", + "name": "url", + "type": "string" + } + ], + "name": "ServerRegistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "serverId", + "type": "uint256" + } + ], + "name": "ServerTrusted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "serverId", + "type": "uint256" + } + ], + "name": "ServerUntrusted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "serverId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "url", + "type": "string" + } + ], + "name": "ServerUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "inputs": [], + "name": "DEFAULT_ADMIN_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAINTAINER_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "UPGRADE_INTERFACE_VERSION", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "serverAddress", + "type": "address" + }, + { + "internalType": "bytes", + "name": "publicKey", + "type": "bytes" + }, + { + "internalType": "string", + "name": "serverUrl", + "type": "string" + } + ], + "internalType": "struct IDataPortabilityServers.AndServerInput", + "name": "addAndTrustServerInput", + "type": "tuple" + } + ], + "name": "addAndTrustServer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "serverAddress", + "type": "address" + }, + { + "internalType": "bytes", + "name": "publicKey", + "type": "bytes" + }, + { + "internalType": "string", + "name": "serverUrl", + "type": "string" + } + ], + "internalType": "struct IDataPortabilityServers.AddAndTrustServerInput", + "name": "addAndTrustServerInput", + "type": "tuple" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "name": "addAndTrustServerWithSignature", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "serverAddress", + "type": "address" + }, + { + "internalType": "bytes", + "name": "publicKey", + "type": "bytes" + }, + { + "internalType": "string", + "name": "serverUrl", + "type": "string" + } + ], + "internalType": "struct IDataPortabilityServers.AndServerInput", + "name": "addServerInput", + "type": "tuple" + } + ], + "name": "addServer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "eip712Domain", + "outputs": [ + { + "internalType": "bytes1", + "name": "fields", + "type": "bytes1" + }, + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "version", + "type": "string" + }, + { + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "verifyingContract", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "salt", + "type": "bytes32" + }, + { + "internalType": "uint256[]", + "name": "extensions", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleAdmin", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRole", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "trustedForwarderAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "ownerAddress", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "serverId", + "type": "uint256" + } + ], + "name": "isActiveServer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "userAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "serverId", + "type": "uint256" + } + ], + "name": "isActiveServerForUser", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "forwarder", + "type": "address" + } + ], + "name": "isTrustedForwarder", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes[]", + "name": "data", + "type": "bytes[]" + } + ], + "name": "multicall", + "outputs": [ + { + "internalType": "bytes[]", + "name": "results", + "type": "bytes[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "paused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proxiableUUID", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "callerConfirmation", + "type": "address" + } + ], + "name": "renounceRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "serverId", + "type": "uint256" + } + ], + "name": "server", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "serverAddress", + "type": "address" + }, + { + "internalType": "bytes", + "name": "publicKey", + "type": "bytes" + }, + { + "internalType": "string", + "name": "url", + "type": "string" + } + ], + "internalType": "struct IDataPortabilityServers.ServerInfo", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serverAddress", + "type": "address" + } + ], + "name": "serverAddressToId", + "outputs": [ + { + "internalType": "uint256", + "name": "serverId", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "serverAddress", + "type": "address" + } + ], + "name": "serverByAddress", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "serverAddress", + "type": "address" + }, + { + "internalType": "bytes", + "name": "publicKey", + "type": "bytes" + }, + { + "internalType": "string", + "name": "url", + "type": "string" + } + ], + "internalType": "struct IDataPortabilityServers.ServerInfo", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "serversCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "adminRole", + "type": "bytes32" + } + ], + "name": "setRoleAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "userAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + } + ], + "name": "setUserNonce", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "serverId", + "type": "uint256" + } + ], + "name": "trustServer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "serverId", + "type": "uint256" + } + ], + "internalType": "struct IDataPortabilityServers.TrustServerInput", + "name": "trustServerInput", + "type": "tuple" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "name": "trustServerWithSignature", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "trustedForwarder", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "unpause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "serverId", + "type": "uint256" + } + ], + "name": "untrustServer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "serverId", + "type": "uint256" + } + ], + "internalType": "struct IDataPortabilityServers.UntrustServerInput", + "name": "untrustServerInput", + "type": "tuple" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "name": "untrustServerWithSignature", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "serverId", + "type": "uint256" + }, + { + "internalType": "string", + "name": "url", + "type": "string" + } + ], + "name": "updateServer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "trustedForwarderAddress", + "type": "address" + } + ], + "name": "updateTrustedForwarder", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "userAddress", + "type": "address" + } + ], + "name": "user", + "outputs": [ + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "trustedServerIds", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "userAddress", + "type": "address" + } + ], + "name": "userNonce", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "userAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "serverIndex", + "type": "uint256" + } + ], + "name": "userServerIdsAt", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "userAddress", + "type": "address" + } + ], + "name": "userServerIdsLength", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "userAddress", + "type": "address" + } + ], + "name": "userServerIdsValues", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + } + ] diff --git a/config/moksha.json b/config/moksha.json index 29f8349..3324acc 100644 --- a/config/moksha.json +++ b/config/moksha.json @@ -20,7 +20,12 @@ "dlpPerformance": true, "queryEngine": true, "dataRefinerRegistry": true, - "dataPermission": true + "dataPermission": false + }, + "v6": { + "dataPortabilityGrantees": true, + "dataPortabilityPermissions": true, + "dataPortabilityServers": true }, "uniswap": { "v3": true diff --git a/config/vana.json b/config/vana.json index 0eb4212..668cdf3 100644 --- a/config/vana.json +++ b/config/vana.json @@ -20,7 +20,12 @@ "dlpPerformance": true, "queryEngine": true, "dataRefinerRegistry": true, - "dataPermission": true + "dataPermission": false + }, + "v6": { + "dataPortabilityGrantees": true, + "dataPortabilityPermissions": true, + "dataPortabilityServers": true }, "uniswap": { "v3": true diff --git a/schema.graphql b/schema.graphql index 81bb18c..3d3a78f 100644 --- a/schema.graphql +++ b/schema.graphql @@ -5,8 +5,8 @@ type User @entity(immutable: false) { files: [File!]! @derivedFrom(field: "owner") "All permissions granted by this user" permissions: [Permission!]! @derivedFrom(field: "grantor") - "All servers trusted by this user" - servers: [Server!]! @derivedFrom(field: "user") + "All server trust relationships for this user" + serverTrusts: [UserServer!]! @derivedFrom(field: "user") } type UserTotals @entity(immutable: false) { @@ -152,11 +152,30 @@ type File @entity(immutable: false) { transactionHash: Bytes! } +type Grantee @entity(immutable: false) { + "The unique ID of the grantee, equivalent to the on-chain granteeId." + id: ID! + "The address of the grantee." + address: Bytes! + "The public key of the grantee." + publicKey: String! + "List of permission IDs associated with this grantee." + permissionIds: [BigInt!]! + "The block number when the grantee was registered." + registeredAtBlock: BigInt! + "The timestamp when the grantee was registered." + registeredAtTimestamp: BigInt! + "The transaction hash of the grantee registration." + transactionHash: Bytes! +} + type Permission @entity(immutable: false) { "The unique ID of the permission, equivalent to the on-chain permissionId." id: ID! "The user who granted the permission." grantor: User! + "The grantee who received the permission." + grantee: Grantee! "The content identifier (e.g., IPFS URL) for the grant details." grant: String! "The nonce used for this permission grant." @@ -176,18 +195,33 @@ type Permission @entity(immutable: false) { } type Server @entity(immutable: false) { - "The unique ID of the Server, equivalent to the on-chain serverId" + "The unique ID of the server, using serverId." + id: ID! + "The URL of the server." + url: String! + "The block number when the server was registered." + registeredAtBlock: BigInt! + "The timestamp when the server was registered." + registeredAtTimestamp: BigInt! + "The transaction hash of the server registration." + transactionHash: Bytes! +} + +type UserServer @entity(immutable: false) { + "Composite ID: userId-serverId" id: ID! "The user who trusts the server." user: User! - "The server's address (ID)." - serverAddress: Bytes! - "The URL of the server." - publicKey: String! - "The URL of the server." - serverUrl: String! + "The server that is trusted." + server: Server! "Timestamp of when the trust was established." trustedAt: BigInt! + "Block number when the trust was established." + trustedAtBlock: BigInt! + "Block number when the trust was revoked (null if still trusted)." + untrustedAtBlock: BigInt + "The transaction hash of the trust establishment." + transactionHash: Bytes! } type Factory @entity { diff --git a/src/lib/contract/v5/data-permission.ts b/src/lib/contract/v5/data-permission.ts deleted file mode 100644 index 85ec742..0000000 --- a/src/lib/contract/v5/data-permission.ts +++ /dev/null @@ -1,115 +0,0 @@ -import { - log, - store, - BigInt as GraphBigInt, - Bytes, -} from "@graphprotocol/graph-ts"; -import { - PermissionAdded, - PermissionRevoked, - ServerTrusted, - ServerUntrusted, - DataPermissionImplementation, -} from "../../../../generated/DataPermissionImplementation/DataPermissionImplementation"; -import { Permission, Server } from "../../../../generated/schema"; -import { getOrCreateUser } from "../shared"; - -export function handlePermissionAdded(event: PermissionAdded): void { - log.info("Handling PermissionAdded with transaction hash: {}", [ - event.transaction.hash.toHexString(), - ]); - - const grantor = getOrCreateUser(event.params.user.toHex()); - const permissionId = event.params.permissionId; - - const permission = new Permission(permissionId.toString()); - permission.grantor = grantor.id; // Renamed from 'user' to 'grantor' - permission.grant = event.params.grant; - permission.addedAtBlock = event.block.number; - permission.addedAtTimestamp = event.block.timestamp; - permission.transactionHash = event.transaction.hash; - - // Set new fields - permission.isActive = true; // New permissions are active by default - permission.fileIds = event.params.fileIds; // Store the new fileIds array - - // Since nonce and signature are not in the event, we must call the contract. - const contract = DataPermissionImplementation.bind(event.address); - const permissionData = contract.try_permissions(permissionId); - - if (!permissionData.reverted) { - // The returned struct has a 'grantor' field, not 'user' - permission.nonce = permissionData.value.nonce; - permission.signature = permissionData.value.signature; - } else { - log.warning( - "Could not get permission data for id {}. Nonce and signature will be zero.", - [permissionId.toString()], - ); - permission.nonce = GraphBigInt.zero(); - permission.signature = new Bytes(0); - } - - permission.save(); -} - -export function handlePermissionRevoked(event: PermissionRevoked): void { - log.info("Handling PermissionRevoked for permissionId: {}", [ - event.params.permissionId.toString(), - ]); - - const permissionId = event.params.permissionId.toString(); - const permission = Permission.load(permissionId); - - if (permission) { - permission.isActive = false; - permission.save(); - } else { - log.warning( - "Received revoke event for a permission not found in subgraph: {}", - [permissionId], - ); - } -} - -export function handleServerTrusted(event: ServerTrusted): void { - log.info("Handling ServerTrusted for user {} and server {}", [ - event.params.user.toHex(), - event.params.serverId.toHex(), - ]); - - const user = getOrCreateUser(event.params.user.toHex()); - const serverId = event.params.serverId; - const compositeId = `${user.id}-${serverId.toHex()}`; - - let server = Server.load(compositeId); - if (server == null) { - server = new Server(compositeId); - server.user = user.id; - server.serverAddress = serverId; - } - - server.serverUrl = event.params.serverUrl; - server.trustedAt = event.block.timestamp; - server.save(); -} - -export function handleServerUntrusted(event: ServerUntrusted): void { - log.info("Handling ServerUntrusted for user {} and server {}", [ - event.params.user.toHex(), - event.params.serverId.toHex(), - ]); - - const userId = event.params.user.toHex(); - const serverId = event.params.serverId.toHex(); - const compositeId = `${userId}-${serverId}`; - - const server = Server.load(compositeId); - if (server != null) { - store.remove("Server", compositeId); - } else { - log.warning("Attempted to untrust a server that was not found: {}", [ - compositeId, - ]); - } -} diff --git a/src/lib/contract/v6/data-portability-grantees.ts b/src/lib/contract/v6/data-portability-grantees.ts new file mode 100644 index 0000000..908c54e --- /dev/null +++ b/src/lib/contract/v6/data-portability-grantees.ts @@ -0,0 +1,32 @@ +import { + log, + BigInt as GraphBigInt, +} from "@graphprotocol/graph-ts"; +import { + GranteeRegistered, +} from "../../../../generated/DataPortabilityGranteesImplementation/DataPortabilityGranteesImplementation"; +import { Grantee } from "../../../../generated/schema"; + +export function handleGranteeRegistered(event: GranteeRegistered): void { + log.info("Handling GranteeRegistered with granteeId: {}, owner: {}, and granteeAddress: {}", [ + event.params.granteeId.toString(), + event.params.owner.toHexString(), + event.params.granteeAddress.toHexString(), + ]); + + const granteeId = event.params.granteeId.toString(); + let grantee = Grantee.load(granteeId); + + if (grantee == null) { + grantee = new Grantee(granteeId); + } + + grantee.address = event.params.granteeAddress; + grantee.publicKey = event.params.publicKey; + grantee.permissionIds = []; + grantee.registeredAtBlock = event.block.number; + grantee.registeredAtTimestamp = event.block.timestamp; + grantee.transactionHash = event.transaction.hash; + + grantee.save(); +} \ No newline at end of file diff --git a/src/lib/contract/v6/data-portability-permissions.ts b/src/lib/contract/v6/data-portability-permissions.ts new file mode 100644 index 0000000..92c7d68 --- /dev/null +++ b/src/lib/contract/v6/data-portability-permissions.ts @@ -0,0 +1,98 @@ +import { + log, + store, + BigInt as GraphBigInt, + Bytes, +} from "@graphprotocol/graph-ts"; +import { + PermissionAdded, + PermissionRevoked, + DataPortabilityPermissionsImplementation, +} from "../../../../generated/DataPortabilityPermissionsImplementation/DataPortabilityPermissionsImplementation"; +import { Permission, Grantee } from "../../../../generated/schema"; +import { getOrCreateUser } from "../shared"; + +export function handlePermissionAdded(event: PermissionAdded): void { + log.info("Handling PermissionAdded with permissionId: {} for user: {} and granteeId: {}", [ + event.params.permissionId.toString(), + event.params.user.toHexString(), + event.params.granteeId.toString(), + ]); + + const grantor = getOrCreateUser(event.params.user.toHex()); + const permissionId = event.params.permissionId.toString(); + const granteeId = event.params.granteeId.toString(); + + // Ensure grantee exists + let grantee = Grantee.load(granteeId); + if (grantee == null) { + log.error("Grantee with id {} not found for permission {}", [granteeId, permissionId]); + return; + } + + // Create permission + const permission = new Permission(permissionId); + permission.grantor = grantor.id; + permission.grantee = grantee.id; + permission.grant = event.params.grant; + permission.addedAtBlock = event.block.number; + permission.addedAtTimestamp = event.block.timestamp; + permission.transactionHash = event.transaction.hash; + permission.isActive = true; + permission.fileIds = event.params.fileIds; + + // Get nonce and signature from contract + const contract = DataPortabilityPermissionsImplementation.bind(event.address); + const permissionData = contract.try_permission(event.params.permissionId); + + if (!permissionData.reverted) { + permission.nonce = permissionData.value.nonce; + permission.signature = permissionData.value.signature; + } else { + log.warning( + "Could not get permission data for id {}. Nonce and signature will be zero.", + [permissionId], + ); + permission.nonce = GraphBigInt.zero(); + permission.signature = new Bytes(0); + } + + permission.save(); + + // Update grantee's permission list + const permissionIds = grantee.permissionIds; + permissionIds.push(event.params.permissionId); + grantee.permissionIds = permissionIds; + grantee.save(); +} + +export function handlePermissionRevoked(event: PermissionRevoked): void { + log.info("Handling PermissionRevoked for permissionId: {}", [ + event.params.permissionId.toString(), + ]); + + const permissionId = event.params.permissionId.toString(); + const permission = Permission.load(permissionId); + + if (permission) { + permission.isActive = false; + permission.save(); + + // Update grantee's permission list + const grantee = Grantee.load(permission.grantee); + if (grantee) { + const permissionIds = grantee.permissionIds; + const index = permissionIds.indexOf(event.params.permissionId); + if (index > -1) { + permissionIds.splice(index, 1); + grantee.permissionIds = permissionIds; + grantee.save(); + } + } + } else { + log.warning( + "Received revoke event for a permission not found in subgraph: {}", + [permissionId], + ); + } +} \ No newline at end of file diff --git a/src/lib/contract/v6/data-portability-servers.ts b/src/lib/contract/v6/data-portability-servers.ts new file mode 100644 index 0000000..c82f5fc --- /dev/null +++ b/src/lib/contract/v6/data-portability-servers.ts @@ -0,0 +1,104 @@ +import { + log, + store, +} from "@graphprotocol/graph-ts"; +import { + ServerRegistered, + ServerUpdated, + ServerTrusted, + ServerUntrusted, +} from "../../../../generated/DataPortabilityServersImplementation/DataPortabilityServersImplementation"; +import { Server, UserServer } from "../../../../generated/schema"; +import { getOrCreateUser } from "../shared"; + +export function handleServerRegistered(event: ServerRegistered): void { + log.info("Handling ServerRegistered with serverId: {}, owner: {}, serverAddress: {}, and url: {}", [ + event.params.serverId.toString(), + event.params.owner.toHexString(), + event.params.serverAddress.toHexString(), + event.params.url, + ]); + + const serverId = event.params.serverId.toString(); + let server = Server.load(serverId); + + if (server == null) { + server = new Server(serverId); + } + + server.url = event.params.url; + server.registeredAtBlock = event.block.number; + server.registeredAtTimestamp = event.block.timestamp; + server.transactionHash = event.transaction.hash; + + server.save(); +} + +export function handleServerUpdated(event: ServerUpdated): void { + log.info("Handling ServerUpdated for serverId: {} with new url: {}", [ + event.params.serverId.toString(), + event.params.url, + ]); + + const serverId = event.params.serverId.toString(); + const server = Server.load(serverId); + + if (server) { + server.url = event.params.url; + server.save(); + } else { + log.warning("Received update event for a server not found in subgraph: {}", [serverId]); + } +} + +export function handleServerTrusted(event: ServerTrusted): void { + log.info("Handling ServerTrusted for user {} and serverId {}", [ + event.params.user.toHex(), + event.params.serverId.toString(), + ]); + + const user = getOrCreateUser(event.params.user.toHex()); + const serverId = event.params.serverId.toString(); + const compositeId = `${user.id}-${serverId}`; + + // Ensure server exists + let server = Server.load(serverId); + if (server == null) { + log.error("Server with id {} not found for trust relationship", [serverId]); + return; + } + + let userServer = UserServer.load(compositeId); + if (userServer == null) { + userServer = new UserServer(compositeId); + userServer.user = user.id; + userServer.server = server.id; + } + + userServer.trustedAt = event.block.timestamp; + userServer.trustedAtBlock = event.block.number; + userServer.transactionHash = event.transaction.hash; + userServer.save(); +} + +export function handleServerUntrusted(event: ServerUntrusted): void { + log.info("Handling ServerUntrusted for user {} and serverId {}", [ + event.params.user.toHex(), + event.params.serverId.toString(), + ]); + + const userId = event.params.user.toHex(); + const serverId = event.params.serverId.toString(); + const compositeId = `${userId}-${serverId}`; + + const userServer = UserServer.load(compositeId); + if (userServer != null) { + // Set the untrusted block instead of removing the entity + userServer.untrustedAtBlock = event.block.number; + userServer.save(); + } else { + log.warning("Attempted to untrust a server relationship that was not found: {}", [ + compositeId, + ]); + } +} \ No newline at end of file diff --git a/src/lib/contract/v6/index.ts b/src/lib/contract/v6/index.ts new file mode 100644 index 0000000..edc1f6a --- /dev/null +++ b/src/lib/contract/v6/index.ts @@ -0,0 +1,15 @@ +export { + handleGranteeRegistered, +} from "./data-portability-grantees"; + +export { + handlePermissionAdded, + handlePermissionRevoked, +} from "./data-portability-permissions"; + +export { + handleServerRegistered, + handleServerUpdated, + handleServerTrusted, + handleServerUntrusted, +} from "./data-portability-servers"; \ No newline at end of file diff --git a/src/mapping.ts.template b/src/mapping.ts.template index 4c5f599..4f5553a 100644 --- a/src/mapping.ts.template +++ b/src/mapping.ts.template @@ -83,6 +83,17 @@ export * from "./lib/contract/v5/dlp-performance"; export * from "./lib/contract/v5/data-permission"; {{/includes.v5.dataPermission}} +// V6 +{{#includes.v6.dataPortabilityGrantees}} +export * from "./lib/contract/v6/data-portability-grantees"; +{{/includes.v6.dataPortabilityGrantees}} +{{#includes.v6.dataPortabilityPermissions}} +export * from "./lib/contract/v6/data-portability-permissions"; +{{/includes.v6.dataPortabilityPermissions}} +{{#includes.v6.dataPortabilityServers}} +export * from "./lib/contract/v6/data-portability-servers"; +{{/includes.v6.dataPortabilityServers}} + //uniswap {{#includes.uniswap.v3}} export * from "./uniswap/v3/mappings/factory"; diff --git a/subgraph.moksha.yaml b/subgraph.moksha.yaml index 49fee4f..26e9593 100644 --- a/subgraph.moksha.yaml +++ b/subgraph.moksha.yaml @@ -35,7 +35,7 @@ dataSources: blockHandlers: - handler: handleBootstrap file: ./src/lib/entity/bootstrap/bootstrap.ts - # v1 +# v1 - kind: ethereum/contract name: DataRegistryImplementationV1 network: moksha @@ -61,7 +61,7 @@ dataSources: handler: handleDataRegistryProofAddedV1 file: ./src/mapping.ts - # v2 +# v2 - kind: ethereum/contract name: DataRegistryImplementationV2 network: moksha @@ -240,13 +240,35 @@ dataSources: handler: handleEpochDlpPerformancesSavedV5 file: ./src/mapping.ts +# v6 - kind: ethereum/contract - name: DataPermissionImplementation + name: DataPortabilityGranteesImplementation network: moksha source: - address: "0x31fb1D48f6B2265A4cAD516BC39E96a18fb7c8de" - abi: DataPermissionImplementation - startBlock: 3517249 + address: "0x2e95B13EBda0009cb2ea398a843a49608AbFdd3d" + abi: DataPortabilityGranteesImplementation + startBlock: 3608836 + mapping: + kind: ethereum/events + apiVersion: 0.0.6 + language: wasm/assemblyscript + entities: + - Grantee + abis: + - name: DataPortabilityGranteesImplementation + file: ./abis/v6/DataPortabilityGranteesImplementation.json + eventHandlers: + - event: GranteeRegistered(indexed uint256,indexed address,indexed address,string) + handler: handleGranteeRegistered + file: ./src/mapping.ts + + - kind: ethereum/contract + name: DataPortabilityPermissionsImplementation + network: moksha + source: + address: "0x0d15681C472082e33Aac426C588d9d0C2264014c" + abi: DataPortabilityPermissionsImplementation + startBlock: 3608836 mapping: kind: ethereum/events apiVersion: 0.0.6 @@ -254,45 +276,48 @@ dataSources: entities: - Permission - User - - Server + - Grantee abis: - - name: DataPermissionImplementation - file: ./abis/v5/DataPermissionImplementation.json + - name: DataPortabilityPermissionsImplementation + file: ./abis/v6/DataPortabilityPermissionsImplementation.json eventHandlers: - - event: PermissionAdded(indexed uint256,indexed address,string,uint256[]) + - event: PermissionAdded(indexed uint256,indexed address,indexed uint256,string,uint256[]) handler: handlePermissionAdded - event: PermissionRevoked(indexed uint256) handler: handlePermissionRevoked - - event: ServerTrusted(indexed address,indexed address,string) - handler: handleServerTrusted - - event: ServerUntrusted(indexed address,indexed address) - handler: handleServerUntrusted file: ./src/mapping.ts - kind: ethereum/contract - name: DataRegistryImplementationV5 + name: DataPortabilityServersImplementation network: moksha source: - address: "0x8C8788f98385F6ba1adD4234e551ABba0f82Cb7C" - abi: DataRegistryImplementationV5 - startBlock: 3425120 + address: "0xE16b4b90c53122663479Dcbcd5f00C2ECF1b3a67" + abi: DataPortabilityServersImplementation + startBlock: 3608836 mapping: kind: ethereum/events apiVersion: 0.0.6 language: wasm/assemblyscript entities: - - EpochReference - - DataRegistryProof + - Server + - UserServer + - User abis: - - name: DataRegistryImplementationV5 - file: ./abis/v5/DataRegistryImplementation.json + - name: DataPortabilityServersImplementation + file: ./abis/v6/DataPortabilityServersImplementation.json eventHandlers: - - event: FileAdded(indexed uint256,indexed address,string) - handler: handleFileAddedV3 - - event: ProofAdded(indexed uint256,indexed address,uint256,indexed uint256,uint256,string) - handler: handleDataRegistryProofAddedV3 + - event: ServerRegistered(indexed uint256,indexed address,indexed address,bytes,string) + handler: handleServerRegistered + - event: ServerUpdated(indexed uint256,string) + handler: handleServerUpdated + - event: ServerTrusted(indexed address,indexed uint256) + handler: handleServerTrusted + - event: ServerUntrusted(indexed address,indexed uint256) + handler: handleServerUntrusted file: ./src/mapping.ts + +# unuiswap - kind: ethereum/contract name: Factory network: moksha diff --git a/subgraph.vana-moksha.yaml b/subgraph.vana-moksha.yaml index 8ceab75..b25634c 100644 --- a/subgraph.vana-moksha.yaml +++ b/subgraph.vana-moksha.yaml @@ -273,6 +273,81 @@ dataSources: handler: handleServerUntrusted file: ./src/mapping.ts + - kind: ethereum/contract + name: DataPortabilityGranteesImplementation + network: vana-moksha + source: + address: "0x0000000000000000000000000000000000000000" + abi: DataPortabilityGranteesImplementation + startBlock: 4000000 + mapping: + kind: ethereum/events + apiVersion: 0.0.6 + language: wasm/assemblyscript + entities: + - Grantee + abis: + - name: DataPortabilityGranteesImplementation + file: ./abis/v6/DataPortabilityGranteesImplementation.json + eventHandlers: + - event: GranteeRegistered(indexed uint256,indexed address,indexed address,string) + handler: handleGranteeRegistered + file: ./src/mapping.ts + + - kind: ethereum/contract + name: DataPortabilityPermissionsImplementation + network: vana-moksha + source: + address: "0x0000000000000000000000000000000000000000" + abi: DataPortabilityPermissionsImplementation + startBlock: 4000000 + mapping: + kind: ethereum/events + apiVersion: 0.0.6 + language: wasm/assemblyscript + entities: + - Permission + - User + - Grantee + abis: + - name: DataPortabilityPermissionsImplementation + file: ./abis/v6/DataPortabilityPermissionsImplementation.json + eventHandlers: + - event: PermissionAdded(indexed uint256,indexed address,indexed uint256,string,uint256[]) + handler: handlePermissionAdded + - event: PermissionRevoked(indexed uint256) + handler: handlePermissionRevoked + file: ./src/mapping.ts + + - kind: ethereum/contract + name: DataPortabilityServersImplementation + network: vana-moksha + source: + address: "0x0000000000000000000000000000000000000000" + abi: DataPortabilityServersImplementation + startBlock: 4000000 + mapping: + kind: ethereum/events + apiVersion: 0.0.6 + language: wasm/assemblyscript + entities: + - Server + - UserServer + - User + abis: + - name: DataPortabilityServersImplementation + file: ./abis/v6/DataPortabilityServersImplementation.json + eventHandlers: + - event: ServerRegistered(indexed uint256,indexed address,indexed address,bytes,string) + handler: handleServerRegistered + - event: ServerUpdated(indexed uint256,string) + handler: handleServerUpdated + - event: ServerTrusted(indexed address,indexed uint256) + handler: handleServerTrusted + - event: ServerUntrusted(indexed address,indexed uint256) + handler: handleServerUntrusted + file: ./src/mapping.ts + - kind: ethereum/contract name: DataRegistryImplementationV5 network: vana-moksha diff --git a/subgraph.vana.yaml b/subgraph.vana.yaml index 1515a12..7c65161 100644 --- a/subgraph.vana.yaml +++ b/subgraph.vana.yaml @@ -269,6 +269,81 @@ dataSources: handler: handleServerUntrusted file: ./src/mapping.ts + - kind: ethereum/contract + name: DataPortabilityGranteesImplementation + network: vana + source: + address: "0x0000000000000000000000000000000000000000" + abi: DataPortabilityGranteesImplementation + startBlock: 4000000 + mapping: + kind: ethereum/events + apiVersion: 0.0.6 + language: wasm/assemblyscript + entities: + - Grantee + abis: + - name: DataPortabilityGranteesImplementation + file: ./abis/v6/DataPortabilityGranteesImplementation.json + eventHandlers: + - event: GranteeRegistered(indexed uint256,indexed address,indexed address,string) + handler: handleGranteeRegistered + file: ./src/mapping.ts + + - kind: ethereum/contract + name: DataPortabilityPermissionsImplementation + network: vana + source: + address: "0x0000000000000000000000000000000000000000" + abi: DataPortabilityPermissionsImplementation + startBlock: 4000000 + mapping: + kind: ethereum/events + apiVersion: 0.0.6 + language: wasm/assemblyscript + entities: + - Permission + - User + - Grantee + abis: + - name: DataPortabilityPermissionsImplementation + file: ./abis/v6/DataPortabilityPermissionsImplementation.json + eventHandlers: + - event: PermissionAdded(indexed uint256,indexed address,indexed uint256,string,uint256[]) + handler: handlePermissionAdded + - event: PermissionRevoked(indexed uint256) + handler: handlePermissionRevoked + file: ./src/mapping.ts + + - kind: ethereum/contract + name: DataPortabilityServersImplementation + network: vana + source: + address: "0x0000000000000000000000000000000000000000" + abi: DataPortabilityServersImplementation + startBlock: 4000000 + mapping: + kind: ethereum/events + apiVersion: 0.0.6 + language: wasm/assemblyscript + entities: + - Server + - UserServer + - User + abis: + - name: DataPortabilityServersImplementation + file: ./abis/v6/DataPortabilityServersImplementation.json + eventHandlers: + - event: ServerRegistered(indexed uint256,indexed address,indexed address,bytes,string) + handler: handleServerRegistered + - event: ServerUpdated(indexed uint256,string) + handler: handleServerUpdated + - event: ServerTrusted(indexed address,indexed uint256) + handler: handleServerTrusted + - event: ServerUntrusted(indexed address,indexed uint256) + handler: handleServerUntrusted + file: ./src/mapping.ts + - kind: ethereum/contract name: DataRegistryImplementationV5 network: vana From 52f8d417f433519fb2625c59556993f647f3e06d Mon Sep 17 00:00:00 2001 From: Eduard Dumea Date: Sat, 19 Jul 2025 01:33:31 +0300 Subject: [PATCH 20/22] add extra fields --- abis/v5/DataPermissionImplementation.json | 1434 ----------------- schema.graphql | 33 +- .../contract/v6/data-portability-grantees.ts | 6 +- .../v6/data-portability-permissions.ts | 56 +- .../contract/v6/data-portability-servers.ts | 6 + subgraph.vana-moksha.yaml | 41 +- subgraph.vana.yaml | 65 +- 7 files changed, 85 insertions(+), 1556 deletions(-) delete mode 100644 abis/v5/DataPermissionImplementation.json diff --git a/abis/v5/DataPermissionImplementation.json b/abis/v5/DataPermissionImplementation.json deleted file mode 100644 index bf65bda..0000000 --- a/abis/v5/DataPermissionImplementation.json +++ /dev/null @@ -1,1434 +0,0 @@ -[ - { - "inputs": [], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "AccessControlBadConfirmation", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "internalType": "bytes32", - "name": "neededRole", - "type": "bytes32" - } - ], - "name": "AccessControlUnauthorizedAccount", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "target", - "type": "address" - } - ], - "name": "AddressEmptyCode", - "type": "error" - }, - { - "inputs": [], - "name": "ECDSAInvalidSignature", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "length", - "type": "uint256" - } - ], - "name": "ECDSAInvalidSignatureLength", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "s", - "type": "bytes32" - } - ], - "name": "ECDSAInvalidSignatureS", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "implementation", - "type": "address" - } - ], - "name": "ERC1967InvalidImplementation", - "type": "error" - }, - { - "inputs": [], - "name": "ERC1967NonPayable", - "type": "error" - }, - { - "inputs": [], - "name": "EmptyGrant", - "type": "error" - }, - { - "inputs": [], - "name": "EmptyUrl", - "type": "error" - }, - { - "inputs": [], - "name": "EnforcedPause", - "type": "error" - }, - { - "inputs": [], - "name": "ExpectedPause", - "type": "error" - }, - { - "inputs": [], - "name": "FailedInnerCall", - "type": "error" - }, - { - "inputs": [], - "name": "GrantAlreadyUsed", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "permissionId", - "type": "uint256" - } - ], - "name": "InactivePermission", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidInitialization", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "expectedNonce", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "providedNonce", - "type": "uint256" - } - ], - "name": "InvalidNonce", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidSignature", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "fileOwner", - "type": "address" - }, - { - "internalType": "address", - "name": "requestor", - "type": "address" - } - ], - "name": "NotFileOwner", - "type": "error" - }, - { - "inputs": [], - "name": "NotInitializing", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "permissionOwner", - "type": "address" - }, - { - "internalType": "address", - "name": "requestor", - "type": "address" - } - ], - "name": "NotPermissionGrantor", - "type": "error" - }, - { - "inputs": [], - "name": "ServerAlreadyRegistered", - "type": "error" - }, - { - "inputs": [], - "name": "ServerNotFound", - "type": "error" - }, - { - "inputs": [], - "name": "ServerNotTrusted", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "existingUrl", - "type": "string" - }, - { - "internalType": "string", - "name": "providedUrl", - "type": "string" - } - ], - "name": "ServerUrlMismatch", - "type": "error" - }, - { - "inputs": [], - "name": "UUPSUnauthorizedCallContext", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "slot", - "type": "bytes32" - } - ], - "name": "UUPSUnsupportedProxiableUUID", - "type": "error" - }, - { - "inputs": [], - "name": "ZeroAddress", - "type": "error" - }, - { - "anonymous": false, - "inputs": [], - "name": "EIP712DomainChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint64", - "name": "version", - "type": "uint64" - } - ], - "name": "Initialized", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Paused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "permissionId", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "user", - "type": "address" - }, - { - "indexed": false, - "internalType": "string", - "name": "grant", - "type": "string" - }, - { - "indexed": false, - "internalType": "uint256[]", - "name": "fileIds", - "type": "uint256[]" - } - ], - "name": "PermissionAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "permissionId", - "type": "uint256" - } - ], - "name": "PermissionRevoked", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "bytes32", - "name": "previousAdminRole", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "bytes32", - "name": "newAdminRole", - "type": "bytes32" - } - ], - "name": "RoleAdminChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "RoleGranted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "RoleRevoked", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "serverId", - "type": "address" - }, - { - "indexed": false, - "internalType": "string", - "name": "url", - "type": "string" - } - ], - "name": "ServerAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "user", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "serverId", - "type": "address" - }, - { - "indexed": false, - "internalType": "string", - "name": "serverUrl", - "type": "string" - } - ], - "name": "ServerTrusted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "user", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "serverId", - "type": "address" - } - ], - "name": "ServerUntrusted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Unpaused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "implementation", - "type": "address" - } - ], - "name": "Upgraded", - "type": "event" - }, - { - "inputs": [], - "name": "DEFAULT_ADMIN_ROLE", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "MAINTAINER_ROLE", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "UPGRADE_INTERFACE_VERSION", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "uint256", - "name": "nonce", - "type": "uint256" - }, - { - "internalType": "string", - "name": "grant", - "type": "string" - }, - { - "internalType": "uint256[]", - "name": "fileIds", - "type": "uint256[]" - } - ], - "internalType": "struct IDataPermissions.PermissionInput", - "name": "permission", - "type": "tuple" - }, - { - "internalType": "bytes", - "name": "signature", - "type": "bytes" - } - ], - "name": "addPermission", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "dataRegistry", - "outputs": [ - { - "internalType": "contract IDataRegistry", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "eip712Domain", - "outputs": [ - { - "internalType": "bytes1", - "name": "fields", - "type": "bytes1" - }, - { - "internalType": "string", - "name": "name", - "type": "string" - }, - { - "internalType": "string", - "name": "version", - "type": "string" - }, - { - "internalType": "uint256", - "name": "chainId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "verifyingContract", - "type": "address" - }, - { - "internalType": "bytes32", - "name": "salt", - "type": "bytes32" - }, - { - "internalType": "uint256[]", - "name": "extensions", - "type": "uint256[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "fileId", - "type": "uint256" - } - ], - "name": "filePermissionIds", - "outputs": [ - { - "internalType": "uint256[]", - "name": "", - "type": "uint256[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - } - ], - "name": "getRoleAdmin", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "grantRole", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "hasRole", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "trustedForwarderAddress", - "type": "address" - }, - { - "internalType": "address", - "name": "ownerAddress", - "type": "address" - }, - { - "internalType": "contract IDataRegistry", - "name": "dataRegistryAddress", - "type": "address" - } - ], - "name": "initialize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "permissionId", - "type": "uint256" - } - ], - "name": "isActivePermission", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "forwarder", - "type": "address" - } - ], - "name": "isTrustedForwarder", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes[]", - "name": "data", - "type": "bytes[]" - } - ], - "name": "multicall", - "outputs": [ - { - "internalType": "bytes[]", - "name": "results", - "type": "bytes[]" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "pause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "paused", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "permissionId", - "type": "uint256" - } - ], - "name": "permissionFileIds", - "outputs": [ - { - "internalType": "uint256[]", - "name": "", - "type": "uint256[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "grant", - "type": "string" - } - ], - "name": "permissionIdByGrant", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "permissionId", - "type": "uint256" - } - ], - "name": "permissions", - "outputs": [ - { - "components": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "address", - "name": "grantor", - "type": "address" - }, - { - "internalType": "uint256", - "name": "nonce", - "type": "uint256" - }, - { - "internalType": "string", - "name": "grant", - "type": "string" - }, - { - "internalType": "bytes", - "name": "signature", - "type": "bytes" - }, - { - "internalType": "bool", - "name": "isActive", - "type": "bool" - }, - { - "internalType": "uint256[]", - "name": "fileIds", - "type": "uint256[]" - } - ], - "internalType": "struct IDataPermissions.PermissionInfo", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "permissionsCount", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "proxiableUUID", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "callerConfirmation", - "type": "address" - } - ], - "name": "renounceRole", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "permissionId", - "type": "uint256" - } - ], - "name": "revokePermission", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "uint256", - "name": "nonce", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "permissionId", - "type": "uint256" - } - ], - "internalType": "struct IDataPermissions.RevokePermissionInput", - "name": "revokePermissionInput", - "type": "tuple" - }, - { - "internalType": "bytes", - "name": "signature", - "type": "bytes" - } - ], - "name": "revokePermissionWithSignature", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "revokeRole", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "serverId", - "type": "address" - } - ], - "name": "servers", - "outputs": [ - { - "components": [ - { - "internalType": "string", - "name": "url", - "type": "string" - } - ], - "internalType": "struct IDataPermissions.Server", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "adminRole", - "type": "bytes32" - } - ], - "name": "setRoleAdmin", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes4", - "name": "interfaceId", - "type": "bytes4" - } - ], - "name": "supportsInterface", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "serverId", - "type": "address" - }, - { - "internalType": "string", - "name": "serverUrl", - "type": "string" - } - ], - "name": "trustServer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "uint256", - "name": "nonce", - "type": "uint256" - }, - { - "internalType": "address", - "name": "serverId", - "type": "address" - }, - { - "internalType": "string", - "name": "serverUrl", - "type": "string" - } - ], - "internalType": "struct IDataPermissions.TrustServerInput", - "name": "trustServerInput", - "type": "tuple" - }, - { - "internalType": "bytes", - "name": "signature", - "type": "bytes" - } - ], - "name": "trustServerWithSignature", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "trustedForwarder", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "unpause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "serverId", - "type": "address" - } - ], - "name": "untrustServer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "uint256", - "name": "nonce", - "type": "uint256" - }, - { - "internalType": "address", - "name": "serverId", - "type": "address" - } - ], - "internalType": "struct IDataPermissions.UntrustServerInput", - "name": "untrustServerInput", - "type": "tuple" - }, - { - "internalType": "bytes", - "name": "signature", - "type": "bytes" - } - ], - "name": "untrustServerWithSignature", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "contract IDataRegistry", - "name": "newDataRegistry", - "type": "address" - } - ], - "name": "updateDataRegistry", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "trustedForwarderAddress", - "type": "address" - } - ], - "name": "updateTrustedForwarder", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "newImplementation", - "type": "address" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "upgradeToAndCall", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "user", - "type": "address" - } - ], - "name": "userNonce", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "user", - "type": "address" - }, - { - "internalType": "uint256", - "name": "permissionIndex", - "type": "uint256" - } - ], - "name": "userPermissionIdsAt", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "user", - "type": "address" - } - ], - "name": "userPermissionIdsLength", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "user", - "type": "address" - } - ], - "name": "userPermissionIdsValues", - "outputs": [ - { - "internalType": "uint256[]", - "name": "", - "type": "uint256[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "user", - "type": "address" - }, - { - "internalType": "uint256", - "name": "permissionIndex", - "type": "uint256" - } - ], - "name": "userRevokedPermissionIdsAt", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "user", - "type": "address" - } - ], - "name": "userRevokedPermissionIdsLength", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "user", - "type": "address" - } - ], - "name": "userRevokedPermissionIdsValues", - "outputs": [ - { - "internalType": "uint256[]", - "name": "", - "type": "uint256[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "user", - "type": "address" - }, - { - "internalType": "uint256", - "name": "serverIndex", - "type": "uint256" - } - ], - "name": "userServerIdsAt", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "user", - "type": "address" - } - ], - "name": "userServerIdsLength", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "user", - "type": "address" - } - ], - "name": "userServerIdsValues", - "outputs": [ - { - "internalType": "address[]", - "name": "", - "type": "address[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "version", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - } -] \ No newline at end of file diff --git a/schema.graphql b/schema.graphql index 3d3a78f..f86ae75 100644 --- a/schema.graphql +++ b/schema.graphql @@ -155,12 +155,14 @@ type File @entity(immutable: false) { type Grantee @entity(immutable: false) { "The unique ID of the grantee, equivalent to the on-chain granteeId." id: ID! + "The owner who registered this grantee." + owner: User! "The address of the grantee." address: Bytes! "The public key of the grantee." publicKey: String! - "List of permission IDs associated with this grantee." - permissionIds: [BigInt!]! + "Permissions associated with this grantee." + permissions: [Permission!]! @derivedFrom(field: "grantee") "The block number when the grantee was registered." registeredAtBlock: BigInt! "The timestamp when the grantee was registered." @@ -182,10 +184,12 @@ type Permission @entity(immutable: false) { nonce: BigInt! "The signature provided by the user." signature: Bytes! - "Whether the permission is currently active or has been revoked." - isActive: Boolean! - "File IDs associated with this permission." - fileIds: [BigInt!]! + "The block number when the permission starts." + startBlock: BigInt! + "The block number when the permission ends (null if no end)." + endBlock: BigInt + "File permissions for this permission." + filePermissions: [PermissionFile!]! @derivedFrom(field: "permission") "The block number when the permission was granted." addedAtBlock: BigInt! "The timestamp when the permission was granted." @@ -194,11 +198,28 @@ type Permission @entity(immutable: false) { transactionHash: Bytes! } +type PermissionFile @entity(immutable: false) { + "Composite ID: permissionId-fileId" + id: ID! + "The permission." + permission: Permission! + "The file." + file: File! +} + type Server @entity(immutable: false) { "The unique ID of the server, using serverId." id: ID! + "The owner who registered this server." + owner: User! + "The server's address." + serverAddress: Bytes! + "The public key of the server." + publicKey: Bytes! "The URL of the server." url: String! + "User trust relationships for this server." + userTrusts: [UserServer!]! @derivedFrom(field: "server") "The block number when the server was registered." registeredAtBlock: BigInt! "The timestamp when the server was registered." diff --git a/src/lib/contract/v6/data-portability-grantees.ts b/src/lib/contract/v6/data-portability-grantees.ts index 908c54e..2ebfad9 100644 --- a/src/lib/contract/v6/data-portability-grantees.ts +++ b/src/lib/contract/v6/data-portability-grantees.ts @@ -6,6 +6,7 @@ import { GranteeRegistered, } from "../../../../generated/DataPortabilityGranteesImplementation/DataPortabilityGranteesImplementation"; import { Grantee } from "../../../../generated/schema"; +import { getOrCreateUser } from "../shared"; export function handleGranteeRegistered(event: GranteeRegistered): void { log.info("Handling GranteeRegistered with granteeId: {}, owner: {}, and granteeAddress: {}", [ @@ -21,9 +22,12 @@ export function handleGranteeRegistered(event: GranteeRegistered): void { grantee = new Grantee(granteeId); } + // Get or create the owner user + const owner = getOrCreateUser(event.params.owner.toHex()); + + grantee.owner = owner.id; grantee.address = event.params.granteeAddress; grantee.publicKey = event.params.publicKey; - grantee.permissionIds = []; grantee.registeredAtBlock = event.block.number; grantee.registeredAtTimestamp = event.block.timestamp; grantee.transactionHash = event.transaction.hash; diff --git a/src/lib/contract/v6/data-portability-permissions.ts b/src/lib/contract/v6/data-portability-permissions.ts index 92c7d68..d574946 100644 --- a/src/lib/contract/v6/data-portability-permissions.ts +++ b/src/lib/contract/v6/data-portability-permissions.ts @@ -9,7 +9,7 @@ import { PermissionRevoked, DataPortabilityPermissionsImplementation, } from "../../../../generated/DataPortabilityPermissionsImplementation/DataPortabilityPermissionsImplementation"; -import { Permission, Grantee } from "../../../../generated/schema"; +import { Permission, Grantee, PermissionFile, File } from "../../../../generated/schema"; import { getOrCreateUser } from "../shared"; export function handlePermissionAdded(event: PermissionAdded): void { @@ -38,8 +38,6 @@ export function handlePermissionAdded(event: PermissionAdded): void { permission.addedAtBlock = event.block.number; permission.addedAtTimestamp = event.block.timestamp; permission.transactionHash = event.transaction.hash; - permission.isActive = true; - permission.fileIds = event.params.fileIds; // Get nonce and signature from contract const contract = DataPortabilityPermissionsImplementation.bind(event.address); @@ -48,6 +46,8 @@ export function handlePermissionAdded(event: PermissionAdded): void { if (!permissionData.reverted) { permission.nonce = permissionData.value.nonce; permission.signature = permissionData.value.signature; + permission.startBlock = permissionData.value.startBlock; + permission.endBlock = permissionData.value.endBlock; } else { log.warning( "Could not get permission data for id {}. Nonce and signature will be zero.", @@ -55,15 +55,40 @@ export function handlePermissionAdded(event: PermissionAdded): void { ); permission.nonce = GraphBigInt.zero(); permission.signature = new Bytes(0); + permission.startBlock = event.block.number; + permission.endBlock = null; } permission.save(); - // Update grantee's permission list - const permissionIds = grantee.permissionIds; - permissionIds.push(event.params.permissionId); - grantee.permissionIds = permissionIds; - grantee.save(); + // Create PermissionFile entities for each fileId + const fileIds = event.params.fileIds; + for (let i = 0; i < fileIds.length; i++) { + const fileId = fileIds[i]; + const permissionFileId = `${permissionId}-${fileId.toString()}`; + + let permissionFile = PermissionFile.load(permissionFileId); + if (permissionFile == null) { + permissionFile = new PermissionFile(permissionFileId); + permissionFile.permission = permission.id; + + // Load or create the file + let file = File.load(fileId.toString()); + if (file == null) { + // Create a placeholder file if it doesn't exist + file = new File(fileId.toString()); + file.owner = grantor.id; + file.url = ""; + file.addedAtBlock = event.block.number; + file.addedAtTimestamp = event.block.timestamp; + file.transactionHash = event.transaction.hash; + file.save(); + } + + permissionFile.file = file.id; + permissionFile.save(); + } + } } export function handlePermissionRevoked(event: PermissionRevoked): void { @@ -75,20 +100,9 @@ export function handlePermissionRevoked(event: PermissionRevoked): void { const permission = Permission.load(permissionId); if (permission) { - permission.isActive = false; + // Set endBlock to indicate when the permission was revoked + permission.endBlock = event.block.number; permission.save(); - - // Update grantee's permission list - const grantee = Grantee.load(permission.grantee); - if (grantee) { - const permissionIds = grantee.permissionIds; - const index = permissionIds.indexOf(event.params.permissionId); - if (index > -1) { - permissionIds.splice(index, 1); - grantee.permissionIds = permissionIds; - grantee.save(); - } - } } else { log.warning( "Received revoke event for a permission not found in subgraph: {}", diff --git a/src/lib/contract/v6/data-portability-servers.ts b/src/lib/contract/v6/data-portability-servers.ts index c82f5fc..84376aa 100644 --- a/src/lib/contract/v6/data-portability-servers.ts +++ b/src/lib/contract/v6/data-portability-servers.ts @@ -26,6 +26,12 @@ export function handleServerRegistered(event: ServerRegistered): void { server = new Server(serverId); } + // Get or create the owner user + const owner = getOrCreateUser(event.params.owner.toHex()); + + server.owner = owner.id; + server.serverAddress = event.params.serverAddress; + server.publicKey = event.params.publicKey; server.url = event.params.url; server.registeredAtBlock = event.block.number; server.registeredAtTimestamp = event.block.timestamp; diff --git a/subgraph.vana-moksha.yaml b/subgraph.vana-moksha.yaml index b25634c..386b48b 100644 --- a/subgraph.vana-moksha.yaml +++ b/subgraph.vana-moksha.yaml @@ -244,42 +244,13 @@ dataSources: handler: handleEpochDlpPerformancesSavedV5 file: ./src/mapping.ts - - kind: ethereum/contract - name: DataPermissionImplementation - network: vana-moksha - source: - address: "0x31fb1D48f6B2265A4cAD516BC39E96a18fb7c8de" - abi: DataPermissionImplementation - startBlock: 3517249 - mapping: - kind: ethereum/events - apiVersion: 0.0.6 - language: wasm/assemblyscript - entities: - - Permission - - User - - Server - abis: - - name: DataPermissionImplementation - file: ./abis/v5/DataPermissionImplementation.json - eventHandlers: - - event: PermissionAdded(indexed uint256,indexed address,string,uint256[]) - handler: handlePermissionAdded - - event: PermissionRevoked(indexed uint256) - handler: handlePermissionRevoked - - event: ServerTrusted(indexed address,indexed address,string) - handler: handleServerTrusted - - event: ServerUntrusted(indexed address,indexed address) - handler: handleServerUntrusted - file: ./src/mapping.ts - - kind: ethereum/contract name: DataPortabilityGranteesImplementation network: vana-moksha source: - address: "0x0000000000000000000000000000000000000000" + address: "0x2e95B13EBda0009cb2ea398a843a49608AbFdd3d" abi: DataPortabilityGranteesImplementation - startBlock: 4000000 + startBlock: 3608836 mapping: kind: ethereum/events apiVersion: 0.0.6 @@ -298,9 +269,9 @@ dataSources: name: DataPortabilityPermissionsImplementation network: vana-moksha source: - address: "0x0000000000000000000000000000000000000000" + address: "0x0d15681C472082e33Aac426C588d9d0C2264014c" abi: DataPortabilityPermissionsImplementation - startBlock: 4000000 + startBlock: 3608836 mapping: kind: ethereum/events apiVersion: 0.0.6 @@ -323,9 +294,9 @@ dataSources: name: DataPortabilityServersImplementation network: vana-moksha source: - address: "0x0000000000000000000000000000000000000000" + address: "0xE16b4b90c53122663479Dcbcd5f00C2ECF1b3a67" abi: DataPortabilityServersImplementation - startBlock: 4000000 + startBlock: 3608836 mapping: kind: ethereum/events apiVersion: 0.0.6 diff --git a/subgraph.vana.yaml b/subgraph.vana.yaml index 7c65161..54bf218 100644 --- a/subgraph.vana.yaml +++ b/subgraph.vana.yaml @@ -240,42 +240,13 @@ dataSources: handler: handleEpochDlpPerformancesSavedV5 file: ./src/mapping.ts - - kind: ethereum/contract - name: DataPermissionImplementation - network: vana - source: - address: "0x31fb1D48f6B2265A4cAD516BC39E96a18fb7c8de" - abi: DataPermissionImplementation - startBlock: 3965727 - mapping: - kind: ethereum/events - apiVersion: 0.0.6 - language: wasm/assemblyscript - entities: - - Permission - - User - - Server - abis: - - name: DataPermissionImplementation - file: ./abis/v5/DataPermissionImplementation.json - eventHandlers: - - event: PermissionAdded(indexed uint256,indexed address,string,uint256[]) - handler: handlePermissionAdded - - event: PermissionRevoked(indexed uint256) - handler: handlePermissionRevoked - - event: ServerTrusted(indexed address,indexed address,string) - handler: handleServerTrusted - - event: ServerUntrusted(indexed address,indexed address) - handler: handleServerUntrusted - file: ./src/mapping.ts - - kind: ethereum/contract name: DataPortabilityGranteesImplementation network: vana source: - address: "0x0000000000000000000000000000000000000000" + address: "0x2e95B13EBda0009cb2ea398a843a49608AbFdd3d" abi: DataPortabilityGranteesImplementation - startBlock: 4000000 + startBlock: 3608836 mapping: kind: ethereum/events apiVersion: 0.0.6 @@ -294,9 +265,9 @@ dataSources: name: DataPortabilityPermissionsImplementation network: vana source: - address: "0x0000000000000000000000000000000000000000" + address: "0x0d15681C472082e33Aac426C588d9d0C2264014c" abi: DataPortabilityPermissionsImplementation - startBlock: 4000000 + startBlock: 3608836 mapping: kind: ethereum/events apiVersion: 0.0.6 @@ -319,9 +290,9 @@ dataSources: name: DataPortabilityServersImplementation network: vana source: - address: "0x0000000000000000000000000000000000000000" + address: "0xE16b4b90c53122663479Dcbcd5f00C2ECF1b3a67" abi: DataPortabilityServersImplementation - startBlock: 4000000 + startBlock: 3608836 mapping: kind: ethereum/events apiVersion: 0.0.6 @@ -344,30 +315,6 @@ dataSources: handler: handleServerUntrusted file: ./src/mapping.ts - - kind: ethereum/contract - name: DataRegistryImplementationV5 - network: vana - source: - address: "0x8C8788f98385F6ba1adD4234e551ABba0f82Cb7C" - abi: DataRegistryImplementationV5 - startBlock: 3425120 - mapping: - kind: ethereum/events - apiVersion: 0.0.6 - language: wasm/assemblyscript - entities: - - EpochReference - - DataRegistryProof - abis: - - name: DataRegistryImplementationV5 - file: ./abis/v5/DataRegistryImplementation.json - eventHandlers: - - event: FileAdded(indexed uint256,indexed address,string) - handler: handleFileAddedV3 - - event: ProofAdded(indexed uint256,indexed address,uint256,indexed uint256,uint256,string) - handler: handleDataRegistryProofAddedV3 - file: ./src/mapping.ts - - kind: ethereum/contract name: Factory network: vana From 78907b6f83d29e8e459f2827ca75a97cab5bc356 Mon Sep 17 00:00:00 2001 From: Eduard Dumea Date: Sat, 19 Jul 2025 01:36:12 +0300 Subject: [PATCH 21/22] fix startBlock --- subgraph.vana.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/subgraph.vana.yaml b/subgraph.vana.yaml index 54bf218..e9a9d5a 100644 --- a/subgraph.vana.yaml +++ b/subgraph.vana.yaml @@ -246,7 +246,7 @@ dataSources: source: address: "0x2e95B13EBda0009cb2ea398a843a49608AbFdd3d" abi: DataPortabilityGranteesImplementation - startBlock: 3608836 + startBlock: 4052868 mapping: kind: ethereum/events apiVersion: 0.0.6 @@ -267,7 +267,7 @@ dataSources: source: address: "0x0d15681C472082e33Aac426C588d9d0C2264014c" abi: DataPortabilityPermissionsImplementation - startBlock: 3608836 + startBlock: 4052868 mapping: kind: ethereum/events apiVersion: 0.0.6 @@ -292,7 +292,7 @@ dataSources: source: address: "0xE16b4b90c53122663479Dcbcd5f00C2ECF1b3a67" abi: DataPortabilityServersImplementation - startBlock: 3608836 + startBlock: 4052868 mapping: kind: ethereum/events apiVersion: 0.0.6 From 63c69768d1fef04d2ebd1a0a60fe134786d3f983 Mon Sep 17 00:00:00 2001 From: Eduard Dumea Date: Thu, 24 Jul 2025 13:14:58 +0300 Subject: [PATCH 22/22] changed contract addresses --- subgraph.moksha.yaml | 6 +++--- subgraph.vana-moksha.yaml | 6 +++--- subgraph.vana.yaml | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/subgraph.moksha.yaml b/subgraph.moksha.yaml index 26e9593..f3963df 100644 --- a/subgraph.moksha.yaml +++ b/subgraph.moksha.yaml @@ -245,7 +245,7 @@ dataSources: name: DataPortabilityGranteesImplementation network: moksha source: - address: "0x2e95B13EBda0009cb2ea398a843a49608AbFdd3d" + address: "0x8325C0A0948483EdA023A1A2Fd895e62C5131234" abi: DataPortabilityGranteesImplementation startBlock: 3608836 mapping: @@ -266,7 +266,7 @@ dataSources: name: DataPortabilityPermissionsImplementation network: moksha source: - address: "0x0d15681C472082e33Aac426C588d9d0C2264014c" + address: "0xD54523048AdD05b4d734aFaE7C68324Ebb7373eF" abi: DataPortabilityPermissionsImplementation startBlock: 3608836 mapping: @@ -291,7 +291,7 @@ dataSources: name: DataPortabilityServersImplementation network: moksha source: - address: "0xE16b4b90c53122663479Dcbcd5f00C2ECF1b3a67" + address: "0x1483B1F634DBA75AeaE60da7f01A679aabd5ee2c" abi: DataPortabilityServersImplementation startBlock: 3608836 mapping: diff --git a/subgraph.vana-moksha.yaml b/subgraph.vana-moksha.yaml index 386b48b..f486ce2 100644 --- a/subgraph.vana-moksha.yaml +++ b/subgraph.vana-moksha.yaml @@ -248,7 +248,7 @@ dataSources: name: DataPortabilityGranteesImplementation network: vana-moksha source: - address: "0x2e95B13EBda0009cb2ea398a843a49608AbFdd3d" + address: "0x8325C0A0948483EdA023A1A2Fd895e62C5131234" abi: DataPortabilityGranteesImplementation startBlock: 3608836 mapping: @@ -269,7 +269,7 @@ dataSources: name: DataPortabilityPermissionsImplementation network: vana-moksha source: - address: "0x0d15681C472082e33Aac426C588d9d0C2264014c" + address: "0xD54523048AdD05b4d734aFaE7C68324Ebb7373eF" abi: DataPortabilityPermissionsImplementation startBlock: 3608836 mapping: @@ -294,7 +294,7 @@ dataSources: name: DataPortabilityServersImplementation network: vana-moksha source: - address: "0xE16b4b90c53122663479Dcbcd5f00C2ECF1b3a67" + address: "0x1483B1F634DBA75AeaE60da7f01A679aabd5ee2c" abi: DataPortabilityServersImplementation startBlock: 3608836 mapping: diff --git a/subgraph.vana.yaml b/subgraph.vana.yaml index e9a9d5a..963257a 100644 --- a/subgraph.vana.yaml +++ b/subgraph.vana.yaml @@ -244,7 +244,7 @@ dataSources: name: DataPortabilityGranteesImplementation network: vana source: - address: "0x2e95B13EBda0009cb2ea398a843a49608AbFdd3d" + address: "0x8325C0A0948483EdA023A1A2Fd895e62C5131234" abi: DataPortabilityGranteesImplementation startBlock: 4052868 mapping: @@ -265,7 +265,7 @@ dataSources: name: DataPortabilityPermissionsImplementation network: vana source: - address: "0x0d15681C472082e33Aac426C588d9d0C2264014c" + address: "0xD54523048AdD05b4d734aFaE7C68324Ebb7373eF" abi: DataPortabilityPermissionsImplementation startBlock: 4052868 mapping: @@ -290,7 +290,7 @@ dataSources: name: DataPortabilityServersImplementation network: vana source: - address: "0xE16b4b90c53122663479Dcbcd5f00C2ECF1b3a67" + address: "0x1483B1F634DBA75AeaE60da7f01A679aabd5ee2c" abi: DataPortabilityServersImplementation startBlock: 4052868 mapping: