Skip to content

Commit a6ec3f1

Browse files
Arweave docs (#141)
* Arweave docs * Edits * Deleting POA * Adding encryption function + Updating FAQ
1 parent 0e1ebd0 commit a6ec3f1

File tree

2 files changed

+232
-0
lines changed

2 files changed

+232
-0
lines changed

navigation/navigation.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,9 @@ export const navigation: (locale: AppLocale) => NavItemDefinition[] = (locale) =
135135
{
136136
slug: 'near',
137137
},
138+
{
139+
slug: 'arweave',
140+
},
138141
],
139142
},
140143
]
Lines changed: 229 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,229 @@
1+
---
2+
title: Building Subgraphs on Arweave
3+
---
4+
5+
> Arweave support in Graph Node and on the Hosted Service is in beta: please reach us on [Discord](https://discord.gg/rC8rBuRtbH) with any questions about building Arweave subgraphs!
6+
7+
In this guide, you will learn how to build and deploy Subgraphs to index the Arweave blockchain.
8+
9+
## What is Arweave?
10+
11+
The Arweave protocol allows developers to store data permanently and that is the main difference between Arweave and IPFS, where IPFS lacks the feature; permanence, and files stored on Arweave can't be changed or deleted.
12+
13+
Arweave already has built numerous libraries for integrating the protocol in a number of different programming languages. For more information you can check:
14+
- [Arwiki](https://arwiki.wiki/#/en/main)
15+
- [Arweave Resources](https://www.arweave.org/build)
16+
17+
## What are Arweave Subgraphs?
18+
19+
The Graph allows you to build custom open APIs called "Subgraphs". Subgraphs are used to tell indexers (server operators) which data to index on a blockchain and save on their servers in order for you to be able to query it at any time using [GraphQL](https://graphql.org/).
20+
21+
[Graph Node](https://github.com/graphprotocol/graph-node) is now able to index data on Arweave protocol. The current integration is only indexing Arweave as a blockchain (blocks and transactions), it is not indexing the stored files yet.
22+
23+
## Building an Arweave Subgraph
24+
25+
To be able to build and deploy Arweave Subgraphs, you need two packages:
26+
1. `@graphprotocol/graph-cli` above version 0.30.2 - This is a command-line tool for building and deploying subgraphs. [Click here](https://www.npmjs.com/package/@graphprotocol/graph-cli) to download using `npm`.
27+
2. `@graphprotocol/graph-ts` above version 0.27.0 - This is library of subgraph-specific types. [Click here](https://www.npmjs.com/package/@graphprotocol/graph-ts) to download using `npm`.
28+
29+
## Subgraph's components
30+
31+
There are three components of a subgraph:
32+
33+
### 1. Manifest - `subgraph.yaml`
34+
35+
Defines the data sources of interest, and how they should be processed. Arweave is a new kind of data source.
36+
37+
### 2. Schema - `schema.graphql`
38+
39+
Here you define which data you want to be able to query after indexing your Subgraph using GraphQL. This is actually similar to a model for an API, where the model defines the structure of a request body.
40+
41+
The requirements for Arweave subgraphs are covered by the [existing documentation](https://thegraph.com/docs/en/developer/create-subgraph-hosted/#the-graphql-schema).
42+
43+
### 3. AssemblyScript Mappings - `mapping.ts`
44+
45+
This is the logic that determines how data should be retrieved and stored when someone interacts with the data sources you are listening to. The data gets translated and is stored based off the schema you have listed.
46+
47+
During subgraph development there are two key commands:
48+
```
49+
$ graph codegen # generates types from the schema file identified in the manifest
50+
$ graph build # generates Web Assembly from the AssemblyScript files, and prepares all the subgraph files in a /build folder
51+
```
52+
53+
## Subgraph Manifest Definition
54+
55+
The subgraph manifest `subgraph.yaml` identifies the data sources for the subgraph, the triggers of interest, and the functions that should be run in response to those triggers. See below for an example subgraph manifest for an Arweave subgraph:
56+
57+
```yaml
58+
specVersion: 0.0.5
59+
description: Arweave Blocks Indexing
60+
schema:
61+
file: ./schema.graphql # link to the schema file
62+
dataSources:
63+
- kind: arweave
64+
name: arweave-blocks
65+
network: arweave-mainnet # The Graph only supports Arweave Mainnet
66+
source:
67+
owner: "ID-OF-AN-OWNER" # The public key of an Arweave wallet
68+
startBlock: 0 # set this to 0 to start indexing from chain genesis
69+
mapping:
70+
apiVersion: 0.0.5
71+
language: wasm/assemblyscript
72+
file: ./src/blocks.ts # link to the file with the Assemblyscript mappings
73+
entities:
74+
- Block
75+
- Transaction
76+
blockHandlers:
77+
- handler: handleBlock # the function name in the mapping file
78+
transactionHandlers:
79+
- handler: handleTx # the function name in the mapping file
80+
```
81+
82+
- Arweave subgraphs introduce a new kind of data source (`arweave`)
83+
- The network should correspond to a network on the hosting Graph Node. On the Hosted Service, Arweave's mainnet is `arweave-mainnet`
84+
- Arweave data sources introduce an optional source.owner field, which is the public key of an Arweave wallet
85+
86+
Arweave data sources support two types of handlers:
87+
88+
- `blockHandlers` - Run on every new Arweave block. No source.owner is required.
89+
- `transactionHandlers` - Run on every transaction where the data source's source.owner is the owner. Note that only exact matches are processed. Currently an owner is required for `transactionHandlers`.
90+
91+
> The source.owner is the owner's Public Key, rather than the owner's address.
92+
93+
> Transactions are the building blocks of the Arweave permaweb and they are objects created by end-users.
94+
95+
> Note: [Bundlr](https://bundlr.network/) transactions are not supported yet.
96+
97+
## Schema Definition
98+
99+
Schema definition describes the structure of the resulting subgraph database and the relationships between entities. This is agnostic of the original data source. There are more details on the subgraph schema definition [here](https://thegraph.com/docs/en/developer/create-subgraph-hosted/#the-graphql-schema).
100+
101+
## AssemblyScript Mappings
102+
103+
The handlers for processing events are written in [AssemblyScript](https://www.assemblyscript.org/).
104+
105+
Arweave indexing introduces Arweave-specific data types to the [AssemblyScript API](https://thegraph.com/docs/en/developer/assemblyscript-api/).
106+
107+
```tsx
108+
class Block {
109+
timestamp: u64
110+
lastRetarget: u64
111+
height: u64
112+
indepHash: Bytes
113+
nonce: Bytes
114+
previousBlock: Bytes
115+
diff: Bytes
116+
hash: Bytes
117+
txRoot: Bytes
118+
txs: Bytes[]
119+
walletList: Bytes
120+
rewardAddr: Bytes
121+
tags: Tag[]
122+
rewardPool: Bytes
123+
weaveSize: Bytes
124+
blockSize: Bytes
125+
cumulativeDiff: Bytes
126+
hashListMerkle: Bytes
127+
poa: ProofOfAccess
128+
}
129+
130+
class Transaction {
131+
format: u32
132+
id: Bytes
133+
lastTx: Bytes
134+
owner: Bytes
135+
tags: Tag[]
136+
target: Bytes
137+
quantity: Bytes
138+
data: Bytes
139+
dataSize: Bytes
140+
dataRoot: Bytes
141+
signature: Bytes
142+
reward: Bytes
143+
}
144+
```
145+
146+
Block handlers receive a `Block`, while transactions receive a `Transaction`.
147+
148+
Writing the mappings of an Arweave Subgraph is very similar to writing the mappings of an Ethereum Subgraph. For more information, click [here](https://thegraph.com/docs/en/developer/create-subgraph-hosted/#writing-mappings).
149+
150+
## Deploying an Arweave Subgraph on the Hosted Service
151+
152+
Once your subgraph has been created on the Hosed Service dashboard, you can deploy by using the `graph deploy` CLI command.
153+
154+
```bash
155+
graph deploy --node https://api.thegraph.com/deploy/ --ipfs https://api.thegraph.com/ipfs/ --access-token <your-access-token>
156+
```
157+
158+
## Querying an Arweave Subgraph
159+
160+
The GraphQL endpoint for Arweave subgraphs is determined by the schema definition, with the existing API interface. Please visit the [GraphQL API documentation](https://thegraph.com/docs/en/developer/graphql-api/) for more information.
161+
162+
## Example Subgraphs
163+
164+
Here is an example subgraph for reference:
165+
- [Example subgraph for Arweave](https://github.com/graphprotocol/example-subgraph/tree/arweave-blocks-transactions)
166+
167+
## FAQ
168+
### Can a subgraph index Arweave and other chains?
169+
No, a subgraph can only support data sources from one chain/network.
170+
171+
### Can I index the stored files on Arweave?
172+
Currently, The Graph is only indexing Arweave as a blockchain (its blocks and transactions).
173+
174+
### Can I identify Bundlr bundles in my subgraph?
175+
This is not currently supported.
176+
177+
### How can I filter transactions to a specific account?
178+
The source.owner is the user's public key, rather than the account address. We are working on adding account filtering support.
179+
180+
### What is the current encryption format?
181+
Data is generally passed into the mappings as Bytes, which if stored directly is returned in the subgraph in a `hex` format (ex. block and transaction hashes). You may want to convert to a `base64` or `base64 URL`-safe format in your mappings, in order to match what is displayed in block explorers like [Arweave Explorer](https://viewblock.io/arweave/).
182+
183+
The following `bytesToBase64(bytes: Uint8Array, urlSafe: boolean): string` helper function can be used, and will be added to `graph-ts`:
184+
185+
```
186+
const base64Alphabet = [
187+
"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M",
188+
"N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z",
189+
"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m",
190+
"n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z",
191+
"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "+", "/"
192+
];
193+
194+
const base64UrlAlphabet = [
195+
"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M",
196+
"N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z",
197+
"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m",
198+
"n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z",
199+
"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "-", "_"
200+
];
201+
202+
function bytesToBase64(bytes: Uint8Array, urlSafe: boolean): string {
203+
let alphabet = urlSafe? base64UrlAlphabet : base64Alphabet;
204+
205+
let result = '', i: i32, l = bytes.length;
206+
for (i = 2; i < l; i += 3) {
207+
result += alphabet[bytes[i - 2] >> 2];
208+
result += alphabet[((bytes[i - 2] & 0x03) << 4) | (bytes[i - 1] >> 4)];
209+
result += alphabet[((bytes[i - 1] & 0x0F) << 2) | (bytes[i] >> 6)];
210+
result += alphabet[bytes[i] & 0x3F];
211+
}
212+
if (i === l + 1) { // 1 octet yet to write
213+
result += alphabet[bytes[i - 2] >> 2];
214+
result += alphabet[(bytes[i - 2] & 0x03) << 4];
215+
if (!urlSafe) {
216+
result += "==";
217+
}
218+
}
219+
if (!urlSafe && i === l) { // 2 octets yet to write
220+
result += alphabet[bytes[i - 2] >> 2];
221+
result += alphabet[((bytes[i - 2] & 0x03) << 4) | (bytes[i - 1] >> 4)];
222+
result += alphabet[(bytes[i - 1] & 0x0F) << 2];
223+
if (!urlSafe) {
224+
result += "=";
225+
}
226+
}
227+
return result;
228+
}
229+
```

0 commit comments

Comments
 (0)