Skip to content

Commit 3e95a5e

Browse files
committed
feat: add receipt recover signer function for graph tally
Signed-off-by: Tomás Migone <tomas@edgeandnode.com>
1 parent 3ac3614 commit 3e95a5e

File tree

2 files changed

+56
-3
lines changed

2 files changed

+56
-3
lines changed

packages/toolshed/src/core/graph-tally.ts

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
import { BytesLike, ethers, id, Signature, Wallet } from 'ethers'
22

3-
import type { RAV } from './types'
3+
import type { RAV, Receipt } from './types'
4+
5+
export const EIP712_DOMAIN_NAME = 'GraphTallyCollector'
6+
export const EIP712_DOMAIN_VERSION = '1'
7+
48
export const EIP712_RAV_PROOF_TYPEHASH = id(
59
'ReceiptAggregateVoucher(bytes32 collectionId,address payer,address serviceProvider,address dataService,uint64 timestampNs,uint128 valueAggregate,bytes metadata)',
610
)
@@ -16,6 +20,22 @@ export const EIP712_RAV_PROOF_TYPES = {
1620
],
1721
}
1822

23+
export const EIP712_RECEIPT_PROOF_TYPEHASH = id(
24+
'Receipt(bytes32 collection_id,address payer,address data_service,address service_provider,uint64 timestamp_ns,uint64 nonce,uint128 value)',
25+
)
26+
27+
export const EIP712_RECEIPT_PROOF_TYPES = {
28+
Receipt: [
29+
{ name: 'collection_id', type: 'bytes32' },
30+
{ name: 'payer', type: 'address' },
31+
{ name: 'data_service', type: 'address' },
32+
{ name: 'service_provider', type: 'address' },
33+
{ name: 'timestamp_ns', type: 'uint64' },
34+
{ name: 'nonce', type: 'uint64' },
35+
{ name: 'value', type: 'uint128' },
36+
],
37+
}
38+
1939
/**
2040
* Generates a signed RAV
2141
* @param allocationId The allocation ID
@@ -44,8 +64,8 @@ export async function generateSignedRAV(
4464
): Promise<{ rav: RAV; signature: string }> {
4565
// Create the domain for the EIP712 signature
4666
const domain = {
47-
name: 'GraphTallyCollector',
48-
version: '1',
67+
name: EIP712_DOMAIN_NAME,
68+
version: EIP712_DOMAIN_VERSION,
4969
chainId,
5070
verifyingContract: graphTallyCollectorAddress,
5171
}
@@ -100,3 +120,26 @@ export function generateSignerProof(
100120
const signer = new Wallet(signerPrivateKey)
101121
return Signature.from(signer.signingKey.sign(proofToDigest)).serialized
102122
}
123+
124+
export function recoverReceiptSigner(
125+
receipt: Receipt,
126+
signature: Uint8Array | string,
127+
graphTallyCollectorAddress: string,
128+
chainId: number,
129+
): string {
130+
// Create the domain for the EIP712 signature
131+
const domain = {
132+
name: EIP712_DOMAIN_NAME,
133+
version: EIP712_DOMAIN_VERSION,
134+
chainId,
135+
verifyingContract: graphTallyCollectorAddress,
136+
}
137+
138+
// Normalize signature to 0x-hex string
139+
const sigHex = typeof signature === 'string' ? signature : ethers.hexlify(signature)
140+
141+
// Recover the signer address from the signature
142+
const signerAddress = ethers.verifyTypedData(domain, EIP712_RECEIPT_PROOF_TYPES, receipt, sigHex)
143+
144+
return signerAddress
145+
}

packages/toolshed/src/core/types.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,13 @@ export type RAV = {
2020
valueAggregate: bigint
2121
metadata: BytesLike
2222
}
23+
24+
export type Receipt = {
25+
collection_id: string
26+
payer: string
27+
data_service: string
28+
service_provider: string
29+
timestamp_ns: bigint
30+
nonce: bigint
31+
value: bigint
32+
}

0 commit comments

Comments
 (0)