diff --git a/subgraph/harb/abis/Harb.json b/subgraph/harb/abis/Harb.json new file mode 100644 index 0000000..3bd9ee8 --- /dev/null +++ b/subgraph/harb/abis/Harb.json @@ -0,0 +1,345 @@ +[ + { + "inputs": [ + { "internalType": "string", "name": "name_", "type": "string" }, + { "internalType": "string", "name": "symbol_", "type": "string" }, + { "internalType": "address", "name": "_factory", "type": "address" }, + { "internalType": "address", "name": "_WETH9", "type": "address" }, + { + "internalType": "contract TwabController", + "name": "twabController_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { "inputs": [], "name": "InvalidShortString", "type": "error" }, + { + "inputs": [{ "internalType": "string", "name": "str", "type": "string" }], + "name": "StringTooLong", + "type": "error" + }, + { "inputs": [], "name": "ZeroAddressInConstructor", "type": "error" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "EIP712DomainChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [], + "name": "DOMAIN_SEPARATOR", + "outputs": [{ "internalType": "bytes32", "name": "", "type": "bytes32" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "TAX_POOL", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "owner", "type": "address" }, + { "internalType": "address", "name": "spender", "type": "address" } + ], + "name": "allowance", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "spender", "type": "address" }, + { "internalType": "uint256", "name": "amount", "type": "uint256" } + ], + "name": "approve", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "_account", "type": "address" } + ], + "name": "balanceOf", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "_amount", "type": "uint256" } + ], + "name": "burn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "_account", "type": "address" } + ], + "name": "claimUbi", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [{ "internalType": "uint8", "name": "", "type": "uint8" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "spender", "type": "address" }, + { + "internalType": "uint256", + "name": "subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseAllowance", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "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": "address", "name": "_account", "type": "address" } + ], + "name": "getUbiDue", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "spender", "type": "address" }, + { "internalType": "uint256", "name": "addedValue", "type": "uint256" } + ], + "name": "increaseAllowance", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "liquidityManager", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "_amount", "type": "uint256" } + ], + "name": "mint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [{ "internalType": "string", "name": "", "type": "string" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "owner", "type": "address" } + ], + "name": "nonces", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "owner", "type": "address" }, + { "internalType": "address", "name": "spender", "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": "permit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "liquidityManager_", + "type": "address" + } + ], + "name": "setLiquidityManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "stakingPool_", "type": "address" } + ], + "name": "setStakingPool", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "stakingPool", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "sumTaxCollected", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "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": "to", "type": "address" }, + { "internalType": "uint256", "name": "amount", "type": "uint256" } + ], + "name": "transfer", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "from", "type": "address" }, + { "internalType": "address", "name": "to", "type": "address" }, + { "internalType": "uint256", "name": "amount", "type": "uint256" } + ], + "name": "transferFrom", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "twabController", + "outputs": [ + { + "internalType": "contract TwabController", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "", "type": "address" }], + "name": "ubiTitles", + "outputs": [ + { + "internalType": "uint256", + "name": "sumTaxCollected", + "type": "uint256" + }, + { "internalType": "uint256", "name": "time", "type": "uint256" } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/subgraph/harb/networks.json b/subgraph/harb/networks.json new file mode 100644 index 0000000..20f30e2 --- /dev/null +++ b/subgraph/harb/networks.json @@ -0,0 +1,8 @@ +{ + "sepolia": { + "Harb": { + "address": "0xcd02666582a2057085edabc55c5120155ba4e93c", + "startBlock": 5510934 + } + } +} \ No newline at end of file diff --git a/subgraph/harb/package.json b/subgraph/harb/package.json new file mode 100644 index 0000000..2cccd4c --- /dev/null +++ b/subgraph/harb/package.json @@ -0,0 +1,18 @@ +{ + "name": "harb", + "license": "UNLICENSED", + "scripts": { + "codegen": "graph codegen", + "build": "graph build", + "deploy": "graph deploy --node https://api.studio.thegraph.com/deploy/ harb", + "create-local": "graph create --node http://localhost:8020/ harb", + "remove-local": "graph remove --node http://localhost:8020/ harb", + "deploy-local": "graph deploy --node http://localhost:8020/ --ipfs http://localhost:5001 harb", + "test": "graph test" + }, + "dependencies": { + "@graphprotocol/graph-cli": "0.68.5", + "@graphprotocol/graph-ts": "0.32.0" + }, + "devDependencies": { "matchstick-as": "0.5.0" } +} diff --git a/subgraph/harb/schema.graphql b/subgraph/harb/schema.graphql new file mode 100644 index 0000000..a1f402e --- /dev/null +++ b/subgraph/harb/schema.graphql @@ -0,0 +1,27 @@ +type Approval @entity(immutable: true) { + id: Bytes! + owner: Bytes! # address + spender: Bytes! # address + value: BigInt! # uint256 + blockNumber: BigInt! + blockTimestamp: BigInt! + transactionHash: Bytes! +} + +type EIP712DomainChanged @entity(immutable: true) { + id: Bytes! + + blockNumber: BigInt! + blockTimestamp: BigInt! + transactionHash: Bytes! +} + +type Transfer @entity(immutable: true) { + id: Bytes! + from: Bytes! # address + to: Bytes! # address + value: BigInt! # uint256 + blockNumber: BigInt! + blockTimestamp: BigInt! + transactionHash: Bytes! +} diff --git a/subgraph/harb/src/harb.ts b/subgraph/harb/src/harb.ts new file mode 100644 index 0000000..e107238 --- /dev/null +++ b/subgraph/harb/src/harb.ts @@ -0,0 +1,50 @@ +import { + Approval as ApprovalEvent, + EIP712DomainChanged as EIP712DomainChangedEvent, + Transfer as TransferEvent +} from "../generated/Harb/Harb" +import { Approval, EIP712DomainChanged, Transfer } from "../generated/schema" + +export function handleApproval(event: ApprovalEvent): void { + let entity = new Approval( + event.transaction.hash.concatI32(event.logIndex.toI32()) + ) + entity.owner = event.params.owner + entity.spender = event.params.spender + entity.value = event.params.value + + entity.blockNumber = event.block.number + entity.blockTimestamp = event.block.timestamp + entity.transactionHash = event.transaction.hash + + entity.save() +} + +export function handleEIP712DomainChanged( + event: EIP712DomainChangedEvent +): void { + let entity = new EIP712DomainChanged( + event.transaction.hash.concatI32(event.logIndex.toI32()) + ) + + entity.blockNumber = event.block.number + entity.blockTimestamp = event.block.timestamp + entity.transactionHash = event.transaction.hash + + entity.save() +} + +export function handleTransfer(event: TransferEvent): void { + let entity = new Transfer( + event.transaction.hash.concatI32(event.logIndex.toI32()) + ) + entity.from = event.params.from + entity.to = event.params.to + entity.value = event.params.value + + entity.blockNumber = event.block.number + entity.blockTimestamp = event.block.timestamp + entity.transactionHash = event.transaction.hash + + entity.save() +} diff --git a/subgraph/harb/subgraph.yaml b/subgraph/harb/subgraph.yaml new file mode 100644 index 0000000..5d0b73f --- /dev/null +++ b/subgraph/harb/subgraph.yaml @@ -0,0 +1,32 @@ +specVersion: 1.0.0 +indexerHints: + prune: auto +schema: + file: ./schema.graphql +dataSources: + - kind: ethereum + name: Harb + network: sepolia + source: + address: "0xcd02666582a2057085edabc55c5120155ba4e93c" + abi: Harb + startBlock: 5510934 + mapping: + kind: ethereum/events + apiVersion: 0.0.7 + language: wasm/assemblyscript + entities: + - Approval + - EIP712DomainChanged + - Transfer + abis: + - name: Harb + file: ./abis/Harb.json + eventHandlers: + - event: Approval(indexed address,indexed address,uint256) + handler: handleApproval + - event: EIP712DomainChanged() + handler: handleEIP712DomainChanged + - event: Transfer(indexed address,indexed address,uint256) + handler: handleTransfer + file: ./src/harb.ts diff --git a/subgraph/harb/tests/harb-utils.ts b/subgraph/harb/tests/harb-utils.ts new file mode 100644 index 0000000..d91644a --- /dev/null +++ b/subgraph/harb/tests/harb-utils.ts @@ -0,0 +1,55 @@ +import { newMockEvent } from "matchstick-as" +import { ethereum, Address, BigInt } from "@graphprotocol/graph-ts" +import { Approval, EIP712DomainChanged, Transfer } from "../generated/Harb/Harb" + +export function createApprovalEvent( + owner: Address, + spender: Address, + value: BigInt +): Approval { + let approvalEvent = changetype(newMockEvent()) + + approvalEvent.parameters = new Array() + + approvalEvent.parameters.push( + new ethereum.EventParam("owner", ethereum.Value.fromAddress(owner)) + ) + approvalEvent.parameters.push( + new ethereum.EventParam("spender", ethereum.Value.fromAddress(spender)) + ) + approvalEvent.parameters.push( + new ethereum.EventParam("value", ethereum.Value.fromUnsignedBigInt(value)) + ) + + return approvalEvent +} + +export function createEIP712DomainChangedEvent(): EIP712DomainChanged { + let eip712DomainChangedEvent = changetype(newMockEvent()) + + eip712DomainChangedEvent.parameters = new Array() + + return eip712DomainChangedEvent +} + +export function createTransferEvent( + from: Address, + to: Address, + value: BigInt +): Transfer { + let transferEvent = changetype(newMockEvent()) + + transferEvent.parameters = new Array() + + transferEvent.parameters.push( + new ethereum.EventParam("from", ethereum.Value.fromAddress(from)) + ) + transferEvent.parameters.push( + new ethereum.EventParam("to", ethereum.Value.fromAddress(to)) + ) + transferEvent.parameters.push( + new ethereum.EventParam("value", ethereum.Value.fromUnsignedBigInt(value)) + ) + + return transferEvent +} diff --git a/subgraph/harb/tests/harb.test.ts b/subgraph/harb/tests/harb.test.ts new file mode 100644 index 0000000..0355603 --- /dev/null +++ b/subgraph/harb/tests/harb.test.ts @@ -0,0 +1,62 @@ +import { + assert, + describe, + test, + clearStore, + beforeAll, + afterAll +} from "matchstick-as/assembly/index" +import { Address, BigInt } from "@graphprotocol/graph-ts" +import { Approval } from "../generated/schema" +import { Approval as ApprovalEvent } from "../generated/Harb/Harb" +import { handleApproval } from "../src/harb" +import { createApprovalEvent } from "./harb-utils" + +// Tests structure (matchstick-as >=0.5.0) +// https://thegraph.com/docs/en/developer/matchstick/#tests-structure-0-5-0 + +describe("Describe entity assertions", () => { + beforeAll(() => { + let owner = Address.fromString("0x0000000000000000000000000000000000000001") + let spender = Address.fromString( + "0x0000000000000000000000000000000000000001" + ) + let value = BigInt.fromI32(234) + let newApprovalEvent = createApprovalEvent(owner, spender, value) + handleApproval(newApprovalEvent) + }) + + afterAll(() => { + clearStore() + }) + + // For more test scenarios, see: + // https://thegraph.com/docs/en/developer/matchstick/#write-a-unit-test + + test("Approval created and stored", () => { + assert.entityCount("Approval", 1) + + // 0xa16081f360e3847006db660bae1c6d1b2e17ec2a is the default address used in newMockEvent() function + assert.fieldEquals( + "Approval", + "0xa16081f360e3847006db660bae1c6d1b2e17ec2a-1", + "owner", + "0x0000000000000000000000000000000000000001" + ) + assert.fieldEquals( + "Approval", + "0xa16081f360e3847006db660bae1c6d1b2e17ec2a-1", + "spender", + "0x0000000000000000000000000000000000000001" + ) + assert.fieldEquals( + "Approval", + "0xa16081f360e3847006db660bae1c6d1b2e17ec2a-1", + "value", + "234" + ) + + // More assert options: + // https://thegraph.com/docs/en/developer/matchstick/#asserts + }) +}) diff --git a/subgraph/harb/tsconfig.json b/subgraph/harb/tsconfig.json new file mode 100644 index 0000000..4e86672 --- /dev/null +++ b/subgraph/harb/tsconfig.json @@ -0,0 +1,4 @@ +{ + "extends": "@graphprotocol/graph-ts/types/tsconfig.base.json", + "include": ["src", "tests"] +}