Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,745 changes: 1,745 additions & 0 deletions abis/RecurringCollector.json

Large diffs are not rendered by default.

110 changes: 110 additions & 0 deletions abis/SubgraphService.json
Original file line number Diff line number Diff line change
Expand Up @@ -2250,5 +2250,115 @@
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "bytes16",
"name": "agreementId",
"type": "bytes16"
}
],
"name": "getIndexingAgreement",
"outputs": [
{
"components": [
{
"components": [
{
"internalType": "address",
"name": "allocationId",
"type": "address"
},
{
"internalType": "enum IIndexingAgreement.IndexingAgreementVersion",
"name": "version",
"type": "uint8"
}
],
"internalType": "struct IIndexingAgreement.State",
"name": "agreement",
"type": "tuple"
},
{
"components": [
{
"internalType": "address",
"name": "dataService",
"type": "address"
},
{
"internalType": "address",
"name": "payer",
"type": "address"
},
{
"internalType": "address",
"name": "serviceProvider",
"type": "address"
},
{
"internalType": "uint64",
"name": "acceptedAt",
"type": "uint64"
},
{
"internalType": "uint64",
"name": "lastCollectionAt",
"type": "uint64"
},
{
"internalType": "uint64",
"name": "endsAt",
"type": "uint64"
},
{
"internalType": "uint256",
"name": "maxInitialTokens",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "maxOngoingTokensPerSecond",
"type": "uint256"
},
{
"internalType": "uint32",
"name": "minSecondsPerCollection",
"type": "uint32"
},
{
"internalType": "uint32",
"name": "maxSecondsPerCollection",
"type": "uint32"
},
{
"internalType": "uint32",
"name": "updateNonce",
"type": "uint32"
},
{
"internalType": "uint64",
"name": "canceledAt",
"type": "uint64"
},
{
"internalType": "enum IRecurringCollector.AgreementState",
"name": "state",
"type": "uint8"
}
],
"internalType": "struct IRecurringCollector.AgreementData",
"name": "collectorAgreement",
"type": "tuple"
}
],
"internalType": "struct IIndexingAgreement.AgreementWrapper",
"name": "",
"type": "tuple"
}
],
"stateMutability": "view",
"type": "function"
}
]
2 changes: 2 additions & 0 deletions config/addresses.template.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export class Addresses {
graphPayments: string
paymentsEscrow: string
graphTallyCollector: string
recurringCollector: string
isL1: boolean
}

Expand Down Expand Up @@ -55,5 +56,6 @@ export let addresses: Addresses = {
graphPayments: '{{graphPayments}}',
paymentsEscrow: '{{paymentsEscrow}}',
graphTallyCollector: '{{graphTallyCollector}}',
recurringCollector: '{{recurringCollector}}',
isL1: {{isL1}},
}
1 change: 1 addition & 0 deletions config/arbitrumSepoliaAddressScript.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ export let addresses: Addresses = {
graphPayments: '{{arbsep.GraphPayments.address}}',
paymentsEscrow: '{{arbsep.PaymentsEscrow.address}}',
graphTallyCollector: '{{arbsep.GraphTallyCollector.address}}',
recurringCollector: '{{arbsep.RecurringCollector.address}}',
isL1: false,
}

Expand Down
1 change: 1 addition & 0 deletions config/localNetworkAddressScript.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ export let addresses: Addresses = {
graphPayments: '{{horizon.GraphPayments.address}}',
paymentsEscrow: '{{horizon.PaymentsEscrow.address}}',
graphTallyCollector: '{{horizon.GraphTallyCollector.address}}',
recurringCollector: '{{horizon.RecurringCollector.address}}',
isL1: false,
}

Expand Down
1 change: 1 addition & 0 deletions config/mainnetArbitrumAddressScript.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ export let addresses: Addresses = {
graphPayments: '{{arbitrum.GraphPayments.address}}',
paymentsEscrow: '{{arbitrum.PaymentsEscrow.address}}',
graphTallyCollector: '{{arbitrum.GraphTallyCollector.address}}',
recurringCollector: '{{arbitrum.RecurringCollector.address}}',
isL1: false,
}

Expand Down
1 change: 1 addition & 0 deletions config/testAddressesL1.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ export let addresses: Addresses = {
graphPayments: '0x0000000000000000000000000000000000000000',
paymentsEscrow: '0x0000000000000000000000000000000000000000',
graphTallyCollector: '0x0000000000000000000000000000000000000000',
recurringCollector: '0x0000000000000000000000000000000000000000',
isL1: true,
}

Expand Down
1 change: 1 addition & 0 deletions config/testAddressesL2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ export let addresses: Addresses = {
graphPayments: '0x0000000000000000000000000000000000000000',
paymentsEscrow: '0x0000000000000000000000000000000000000000',
graphTallyCollector: '0x0000000000000000000000000000000000000000',
recurringCollector: '0x0000000000000000000000000000000000000000',
isL1: false,
}

Expand Down
39 changes: 39 additions & 0 deletions schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -1892,4 +1892,43 @@ type Signer @entity(immutable: false) {
payer: Payer!
"The thaw end timestamp for revoking the signer"
thawEndTimestamp: BigInt!
}

type IndexingAgreement @entity(immutable: false) {
"The agreement ID (bytes16)"
id: Bytes!
"The data service address (SubgraphService)"
dataService: Bytes!
"The payer address"
payer: Bytes!
"The service provider (indexer) address"
serviceProvider: Bytes!
"The allocation linked to this agreement"
allocationId: Bytes!
"The subgraph deployment ID"
subgraphDeploymentId: Bytes!
"Agreement state: 0=NotAccepted, 1=Accepted, 2=CanceledByServiceProvider, 3=CanceledByPayer"
state: Int!
"Timestamp when the agreement was accepted"
acceptedAt: BigInt!
"Timestamp of last collection"
lastCollectionAt: BigInt!
"Timestamp when the agreement ends"
endsAt: BigInt!
"Maximum tokens for first collection"
maxInitialTokens: BigInt!
"Maximum tokens per second for ongoing collections"
maxOngoingTokensPerSecond: BigInt!
"Tokens per second from agreement terms"
tokensPerSecond: BigInt!
"Tokens per entity per second from agreement terms"
tokensPerEntityPerSecond: BigInt!
"Minimum seconds between collections"
minSecondsPerCollection: Int!
"Maximum seconds between collections"
maxSecondsPerCollection: Int!
"Timestamp when agreement was canceled (0 if not canceled)"
canceledAt: BigInt!
"Total tokens collected over lifetime"
tokensCollected: BigInt!
}
91 changes: 91 additions & 0 deletions src/mappings/recurringCollector.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import { Address, BigInt, Bytes } from '@graphprotocol/graph-ts'
import { IndexingAgreement } from '../types/schema'
import {
AgreementAccepted,
AgreementCanceled,
AgreementUpdated,
RCACollected,
} from '../types/RecurringCollector/RecurringCollector'
import { SubgraphService } from '../types/RecurringCollector/SubgraphService'
import { addresses } from '../../config/addresses'

const BIGINT_ZERO = BigInt.fromI32(0)
const BYTES_ZERO = Bytes.fromI32(0)

export function handleAgreementAccepted(event: AgreementAccepted): void {
let agreement = new IndexingAgreement(event.params.agreementId)

agreement.dataService = event.params.dataService
agreement.payer = event.params.payer
agreement.serviceProvider = event.params.serviceProvider
agreement.state = 1 // Accepted
agreement.acceptedAt = event.params.acceptedAt
agreement.lastCollectionAt = event.params.acceptedAt
agreement.endsAt = event.params.endsAt
agreement.maxInitialTokens = event.params.maxInitialTokens
agreement.maxOngoingTokensPerSecond = event.params.maxOngoingTokensPerSecond
agreement.minSecondsPerCollection = event.params.minSecondsPerCollection.toI32()
agreement.maxSecondsPerCollection = event.params.maxSecondsPerCollection.toI32()
agreement.canceledAt = BIGINT_ZERO
agreement.tokensCollected = BIGINT_ZERO

// Get allocationId and subgraphDeploymentId from SubgraphService
let subgraphService = SubgraphService.bind(Address.fromString(addresses.subgraphService))
let iaResult = subgraphService.try_getIndexingAgreement(event.params.agreementId)
if (!iaResult.reverted) {
let allocationId = iaResult.value.agreement.allocationId
agreement.allocationId = allocationId

let allocResult = subgraphService.try_getAllocation(allocationId)
if (!allocResult.reverted) {
agreement.subgraphDeploymentId = allocResult.value.subgraphDeploymentId
} else {
agreement.subgraphDeploymentId = BYTES_ZERO
}
} else {
agreement.allocationId = BYTES_ZERO
agreement.subgraphDeploymentId = BYTES_ZERO
}

// Terms: tokensPerSecond and tokensPerEntityPerSecond come from decoded metadata.
// Set to zero for now — will be populated when we add metadata decoding.
agreement.tokensPerSecond = BIGINT_ZERO
agreement.tokensPerEntityPerSecond = BIGINT_ZERO

agreement.save()
}

export function handleAgreementCanceled(event: AgreementCanceled): void {
let agreement = IndexingAgreement.load(event.params.agreementId)
if (agreement == null) return

// canceledBy: 0=ServiceProvider, 1=Payer, 2=ThirdParty
if (event.params.canceledBy == 0) {
agreement.state = 2 // CanceledByServiceProvider
} else {
agreement.state = 3 // CanceledByPayer
}
agreement.canceledAt = event.params.canceledAt
agreement.save()
}

export function handleAgreementUpdated(event: AgreementUpdated): void {
let agreement = IndexingAgreement.load(event.params.agreementId)
if (agreement == null) return

agreement.endsAt = event.params.endsAt
agreement.maxInitialTokens = event.params.maxInitialTokens
agreement.maxOngoingTokensPerSecond = event.params.maxOngoingTokensPerSecond
agreement.minSecondsPerCollection = event.params.minSecondsPerCollection.toI32()
agreement.maxSecondsPerCollection = event.params.maxSecondsPerCollection.toI32()
agreement.save()
}

export function handleRCACollected(event: RCACollected): void {
let agreement = IndexingAgreement.load(event.params.agreementId)
if (agreement == null) return

agreement.lastCollectionAt = event.block.timestamp
agreement.tokensCollected = agreement.tokensCollected.plus(event.params.tokens)
agreement.save()
}
28 changes: 28 additions & 0 deletions subgraph.template.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -673,6 +673,34 @@ dataSources:
handler: handleSignerRevoked
- event: PaymentCollected(uint8,indexed bytes32,indexed address,address,indexed address,uint256)
handler: handlePaymentCollected
- kind: ethereum/contract
name: RecurringCollector
network: {{network}}
source:
address: "{{recurringCollector}}"
abi: RecurringCollector
startBlock: {{blockNumber}}
mapping:
kind: ethereum/events
apiVersion: 0.0.9
language: wasm/assemblyscript
file: ./src/mappings/recurringCollector.ts
entities:
- IndexingAgreement
abis:
- name: RecurringCollector
file: ./abis/RecurringCollector.json
- name: SubgraphService
file: ./abis/SubgraphService.json
eventHandlers:
- event: AgreementAccepted(indexed address,indexed address,indexed address,bytes16,uint64,uint64,uint256,uint256,uint32,uint32)
handler: handleAgreementAccepted
- event: AgreementCanceled(indexed address,indexed address,indexed address,bytes16,uint64,uint8)
handler: handleAgreementCanceled
- event: AgreementUpdated(indexed address,indexed address,indexed address,bytes16,uint64,uint64,uint256,uint256,uint32,uint32)
handler: handleAgreementUpdated
- event: RCACollected(indexed address,indexed address,indexed address,bytes16,bytes32,uint256,uint256)
handler: handleRCACollected
- kind: ethereum/contract
name: HorizonDisputeManager
network: {{network}}
Expand Down
Loading
Loading