first deployment
This commit is contained in:
parent
0de3370f48
commit
f749975c81
11 changed files with 453 additions and 64 deletions
4
subgraph/harb/.gitignore
vendored
Normal file
4
subgraph/harb/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
build/
|
||||
node_modules/
|
||||
generated/
|
||||
yarn.lock
|
||||
9
subgraph/harb/README.md
Normal file
9
subgraph/harb/README.md
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
|
||||
|
||||
## deployment
|
||||
|
||||
```
|
||||
yarn codegen
|
||||
yarn build
|
||||
yarn deploy
|
||||
```
|
||||
209
subgraph/harb/abis/Stake.json
Normal file
209
subgraph/harb/abis/Stake.json
Normal file
|
|
@ -0,0 +1,209 @@
|
|||
[
|
||||
{
|
||||
"inputs": [
|
||||
{ "internalType": "address", "name": "_tokenContract", "type": "address" }
|
||||
],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "constructor"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{ "internalType": "address", "name": "receiver", "type": "address" },
|
||||
{ "internalType": "uint256", "name": "stakeWanted", "type": "uint256" },
|
||||
{ "internalType": "uint256", "name": "availableStake", "type": "uint256" }
|
||||
],
|
||||
"name": "ExceededAvailableStake",
|
||||
"type": "error"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{ "internalType": "address", "name": "requester", "type": "address" },
|
||||
{ "internalType": "address", "name": "owner", "type": "address" }
|
||||
],
|
||||
"name": "NoPermission",
|
||||
"type": "error"
|
||||
},
|
||||
{ "inputs": [], "name": "PositionNotFound", "type": "error" },
|
||||
{
|
||||
"inputs": [
|
||||
{ "internalType": "address", "name": "receiver", "type": "address" },
|
||||
{ "internalType": "uint256", "name": "assets", "type": "uint256" },
|
||||
{ "internalType": "uint256", "name": "sharesWanted", "type": "uint256" },
|
||||
{ "internalType": "uint256", "name": "minStake", "type": "uint256" }
|
||||
],
|
||||
"name": "SharesTooLow",
|
||||
"type": "error"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{ "internalType": "address", "name": "receiver", "type": "address" },
|
||||
{ "internalType": "uint64", "name": "taxRateWanted", "type": "uint64" },
|
||||
{ "internalType": "uint64", "name": "taxRateMet", "type": "uint64" },
|
||||
{ "internalType": "uint256", "name": "positionId", "type": "uint256" }
|
||||
],
|
||||
"name": "TaxTooLow",
|
||||
"type": "error"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "uint256",
|
||||
"name": "positionId",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "address",
|
||||
"name": "owner",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint256",
|
||||
"name": "share",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint32",
|
||||
"name": "creationTime",
|
||||
"type": "uint32"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint32",
|
||||
"name": "taxRate",
|
||||
"type": "uint32"
|
||||
}
|
||||
],
|
||||
"name": "PositionCreated",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "uint256",
|
||||
"name": "positionId",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint256",
|
||||
"name": "share",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint32",
|
||||
"name": "lastTaxTime",
|
||||
"type": "uint32"
|
||||
}
|
||||
],
|
||||
"name": "PositionRemoved",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "dormantSupply",
|
||||
"outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{ "internalType": "uint256", "name": "positionId", "type": "uint256" }
|
||||
],
|
||||
"name": "exitPosition",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "minStake",
|
||||
"outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "nextPositionId",
|
||||
"outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "outstandingStake",
|
||||
"outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{ "internalType": "uint256", "name": "positionID", "type": "uint256" }
|
||||
],
|
||||
"name": "payTax",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],
|
||||
"name": "positions",
|
||||
"outputs": [
|
||||
{ "internalType": "uint256", "name": "share", "type": "uint256" },
|
||||
{ "internalType": "address", "name": "owner", "type": "address" },
|
||||
{ "internalType": "uint32", "name": "creationTime", "type": "uint32" },
|
||||
{ "internalType": "uint32", "name": "lastTaxTime", "type": "uint32" },
|
||||
{ "internalType": "uint32", "name": "taxRate", "type": "uint32" }
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{ "internalType": "uint256", "name": "assets", "type": "uint256" },
|
||||
{ "internalType": "address", "name": "receiver", "type": "address" },
|
||||
{ "internalType": "uint32", "name": "taxRate", "type": "uint32" },
|
||||
{
|
||||
"internalType": "uint256[]",
|
||||
"name": "positionsToSnatch",
|
||||
"type": "uint256[]"
|
||||
}
|
||||
],
|
||||
"name": "snatch",
|
||||
"outputs": [
|
||||
{ "internalType": "uint256", "name": "positionId", "type": "uint256" }
|
||||
],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{ "internalType": "uint256", "name": "positionID", "type": "uint256" },
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "taxFloorDuration",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "taxDue",
|
||||
"outputs": [
|
||||
{ "internalType": "uint256", "name": "amountDue", "type": "uint256" }
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "totalSupply",
|
||||
"outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
}
|
||||
]
|
||||
|
|
@ -3,6 +3,10 @@
|
|||
"Harb": {
|
||||
"address": "0xcd02666582a2057085edabc55c5120155ba4e93c",
|
||||
"startBlock": 5510934
|
||||
},
|
||||
"Stake": {
|
||||
"address": "0x4256777543814d66f9f66390f6bb33c55a24c331",
|
||||
"startBlock": 5510934
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -12,7 +12,8 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"@graphprotocol/graph-cli": "0.68.5",
|
||||
"@graphprotocol/graph-ts": "0.32.0"
|
||||
"@graphprotocol/graph-ts": "0.32.0",
|
||||
"assemblyscript": "0.19.23"
|
||||
},
|
||||
"devDependencies": { "matchstick-as": "0.5.0" }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,27 +1,23 @@
|
|||
type Approval @entity(immutable: true) {
|
||||
|
||||
type Stats @entity {
|
||||
id: Bytes!
|
||||
outstandingSupply: BigInt! # uint256
|
||||
activeSupply: BigInt! # uint256
|
||||
}
|
||||
|
||||
enum PositionStatus {
|
||||
Active,
|
||||
Closed,
|
||||
}
|
||||
|
||||
type Position @entity {
|
||||
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!
|
||||
share: BigDecimal!
|
||||
# harb at start
|
||||
# current harb value
|
||||
creationTime: Int!
|
||||
lastTaxTime: Int
|
||||
taxRate: BigDecimal!
|
||||
status: PositionStatus!
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,48 +3,17 @@ import {
|
|||
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()
|
||||
|
||||
}
|
||||
|
|
|
|||
27
subgraph/harb/src/stake.ts
Normal file
27
subgraph/harb/src/stake.ts
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
import {
|
||||
PositionCreated as PositionCreatedEvent,
|
||||
PositionRemoved as PositionRemovedEvent,
|
||||
} from "../generated/Stake/Stake"
|
||||
import { BigDecimal, BigInt, Bytes } from "@graphprotocol/graph-ts"
|
||||
import { Position } from "../generated/schema"
|
||||
|
||||
let decimals: BigDecimal = BigDecimal.fromString("1000000000000000000")
|
||||
let totalSupply: BigDecimal = BigDecimal.fromString("10000000000000000000000000")
|
||||
|
||||
export function handlePositionCreated(event: PositionCreatedEvent): void {
|
||||
let position = new Position(Bytes.fromI32(event.params.positionId.toI32()))
|
||||
position.owner = event.params.owner
|
||||
position.share = event.params.share.toBigDecimal().div(totalSupply)
|
||||
position.creationTime = event.params.creationTime.toI32();
|
||||
position.taxRate = event.params.taxRate.toBigDecimal().div(BigDecimal.fromString("100"))
|
||||
position.status = "Active"
|
||||
position.save()
|
||||
}
|
||||
|
||||
export function handlePositionRemoved(event: PositionRemovedEvent): void {
|
||||
let position = Position.load(Bytes.fromI32(event.params.positionId.toI32()))
|
||||
if (position != null) {
|
||||
position.status = "Closed"
|
||||
position.save()
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
specVersion: 1.0.0
|
||||
indexerHints:
|
||||
prune: auto
|
||||
specVersion: 0.0.4
|
||||
repository: http://gitea.loseyourip.com:4000/dark-meme-society/harb.git
|
||||
description: Harberger Tax Token
|
||||
schema:
|
||||
file: ./schema.graphql
|
||||
dataSources:
|
||||
|
|
@ -16,9 +16,7 @@ dataSources:
|
|||
apiVersion: 0.0.7
|
||||
language: wasm/assemblyscript
|
||||
entities:
|
||||
- Approval
|
||||
- EIP712DomainChanged
|
||||
- Transfer
|
||||
- Stats
|
||||
abis:
|
||||
- name: Harb
|
||||
file: ./abis/Harb.json
|
||||
|
|
@ -30,3 +28,25 @@ dataSources:
|
|||
- event: Transfer(indexed address,indexed address,uint256)
|
||||
handler: handleTransfer
|
||||
file: ./src/harb.ts
|
||||
- kind: ethereum
|
||||
name: Stake
|
||||
network: sepolia
|
||||
source:
|
||||
address: "0x4256777543814d66f9f66390f6bb33c55a24c331"
|
||||
abi: Stake
|
||||
startBlock: 5510935
|
||||
mapping:
|
||||
kind: ethereum/events
|
||||
apiVersion: 0.0.7
|
||||
language: wasm/assemblyscript
|
||||
entities:
|
||||
- Position
|
||||
abis:
|
||||
- name: Stake
|
||||
file: ./abis/Stake.json
|
||||
eventHandlers:
|
||||
- event: PositionCreated(indexed uint256,indexed address,uint256,uint32,uint32)
|
||||
handler: handlePositionCreated
|
||||
- event: PositionRemoved(indexed uint256,uint256,uint32)
|
||||
handler: handlePositionRemoved
|
||||
file: ./src/stake.ts
|
||||
|
|
|
|||
70
subgraph/harb/tests/stake-utils.ts
Normal file
70
subgraph/harb/tests/stake-utils.ts
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
import { newMockEvent } from "matchstick-as"
|
||||
import { ethereum, BigInt, Address } from "@graphprotocol/graph-ts"
|
||||
import { PositionCreated, PositionRemoved } from "../generated/Stake/Stake"
|
||||
|
||||
export function createPositionCreatedEvent(
|
||||
positionId: BigInt,
|
||||
owner: Address,
|
||||
share: BigInt,
|
||||
creationTime: BigInt,
|
||||
taxRate: BigInt
|
||||
): PositionCreated {
|
||||
let positionCreatedEvent = changetype<PositionCreated>(newMockEvent())
|
||||
|
||||
positionCreatedEvent.parameters = new Array()
|
||||
|
||||
positionCreatedEvent.parameters.push(
|
||||
new ethereum.EventParam(
|
||||
"positionId",
|
||||
ethereum.Value.fromUnsignedBigInt(positionId)
|
||||
)
|
||||
)
|
||||
positionCreatedEvent.parameters.push(
|
||||
new ethereum.EventParam("owner", ethereum.Value.fromAddress(owner))
|
||||
)
|
||||
positionCreatedEvent.parameters.push(
|
||||
new ethereum.EventParam("share", ethereum.Value.fromUnsignedBigInt(share))
|
||||
)
|
||||
positionCreatedEvent.parameters.push(
|
||||
new ethereum.EventParam(
|
||||
"creationTime",
|
||||
ethereum.Value.fromUnsignedBigInt(creationTime)
|
||||
)
|
||||
)
|
||||
positionCreatedEvent.parameters.push(
|
||||
new ethereum.EventParam(
|
||||
"taxRate",
|
||||
ethereum.Value.fromUnsignedBigInt(taxRate)
|
||||
)
|
||||
)
|
||||
|
||||
return positionCreatedEvent
|
||||
}
|
||||
|
||||
export function createPositionRemovedEvent(
|
||||
positionId: BigInt,
|
||||
share: BigInt,
|
||||
lastTaxTime: BigInt
|
||||
): PositionRemoved {
|
||||
let positionRemovedEvent = changetype<PositionRemoved>(newMockEvent())
|
||||
|
||||
positionRemovedEvent.parameters = new Array()
|
||||
|
||||
positionRemovedEvent.parameters.push(
|
||||
new ethereum.EventParam(
|
||||
"positionId",
|
||||
ethereum.Value.fromUnsignedBigInt(positionId)
|
||||
)
|
||||
)
|
||||
positionRemovedEvent.parameters.push(
|
||||
new ethereum.EventParam("share", ethereum.Value.fromUnsignedBigInt(share))
|
||||
)
|
||||
positionRemovedEvent.parameters.push(
|
||||
new ethereum.EventParam(
|
||||
"lastTaxTime",
|
||||
ethereum.Value.fromUnsignedBigInt(lastTaxTime)
|
||||
)
|
||||
)
|
||||
|
||||
return positionRemovedEvent
|
||||
}
|
||||
80
subgraph/harb/tests/stake.test.ts
Normal file
80
subgraph/harb/tests/stake.test.ts
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
import {
|
||||
assert,
|
||||
describe,
|
||||
test,
|
||||
clearStore,
|
||||
beforeAll,
|
||||
afterAll
|
||||
} from "matchstick-as/assembly/index"
|
||||
import { BigInt, Address } from "@graphprotocol/graph-ts"
|
||||
import { PositionCreated } from "../generated/schema"
|
||||
import { PositionCreated as PositionCreatedEvent } from "../generated/Stake/Stake"
|
||||
import { handlePositionCreated } from "../src/stake"
|
||||
import { createPositionCreatedEvent } from "./stake-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 positionId = BigInt.fromI32(234)
|
||||
let owner = Address.fromString("0x0000000000000000000000000000000000000001")
|
||||
let share = BigInt.fromI32(234)
|
||||
let creationTime = BigInt.fromI32(234)
|
||||
let taxRate = BigInt.fromI32(234)
|
||||
let newPositionCreatedEvent = createPositionCreatedEvent(
|
||||
positionId,
|
||||
owner,
|
||||
share,
|
||||
creationTime,
|
||||
taxRate
|
||||
)
|
||||
handlePositionCreated(newPositionCreatedEvent)
|
||||
})
|
||||
|
||||
afterAll(() => {
|
||||
clearStore()
|
||||
})
|
||||
|
||||
// For more test scenarios, see:
|
||||
// https://thegraph.com/docs/en/developer/matchstick/#write-a-unit-test
|
||||
|
||||
test("PositionCreated created and stored", () => {
|
||||
assert.entityCount("PositionCreated", 1)
|
||||
|
||||
// 0xa16081f360e3847006db660bae1c6d1b2e17ec2a is the default address used in newMockEvent() function
|
||||
assert.fieldEquals(
|
||||
"PositionCreated",
|
||||
"0xa16081f360e3847006db660bae1c6d1b2e17ec2a-1",
|
||||
"positionId",
|
||||
"234"
|
||||
)
|
||||
assert.fieldEquals(
|
||||
"PositionCreated",
|
||||
"0xa16081f360e3847006db660bae1c6d1b2e17ec2a-1",
|
||||
"owner",
|
||||
"0x0000000000000000000000000000000000000001"
|
||||
)
|
||||
assert.fieldEquals(
|
||||
"PositionCreated",
|
||||
"0xa16081f360e3847006db660bae1c6d1b2e17ec2a-1",
|
||||
"share",
|
||||
"234"
|
||||
)
|
||||
assert.fieldEquals(
|
||||
"PositionCreated",
|
||||
"0xa16081f360e3847006db660bae1c6d1b2e17ec2a-1",
|
||||
"creationTime",
|
||||
"234"
|
||||
)
|
||||
assert.fieldEquals(
|
||||
"PositionCreated",
|
||||
"0xa16081f360e3847006db660bae1c6d1b2e17ec2a-1",
|
||||
"taxRate",
|
||||
"234"
|
||||
)
|
||||
|
||||
// More assert options:
|
||||
// https://thegraph.com/docs/en/developer/matchstick/#asserts
|
||||
})
|
||||
})
|
||||
Loading…
Add table
Add a link
Reference in a new issue