create-ponder 0.2.8 → 0.2.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +11 -1
- package/package.json +1 -1
- package/templates/feature-multichain/_dot_env.local +3 -0
- package/templates/feature-multichain/ponder.config.ts +18 -0
- package/templates/reference-erc1155/README.md +24 -0
- package/templates/reference-erc1155/_dot_env.local +5 -0
- package/templates/reference-erc1155/_dot_eslintrc.json +3 -0
- package/templates/reference-erc1155/_dot_gitignore +18 -0
- package/templates/reference-erc1155/abis/erc1155Abi.ts +162 -0
- package/templates/reference-erc1155/package.json +25 -0
- package/templates/reference-erc1155/ponder-env.d.ts +27 -0
- package/templates/reference-erc1155/ponder.config.ts +20 -0
- package/templates/reference-erc1155/ponder.schema.ts +29 -0
- package/templates/reference-erc1155/src/index.ts +109 -0
- package/templates/reference-erc1155/tsconfig.json +26 -0
- package/templates/reference-erc20/README.md +1 -1
- package/templates/reference-erc20/abis/erc20ABI.ts +147 -0
- package/templates/reference-erc20/package.json +0 -1
- package/templates/reference-erc20/ponder.config.ts +1 -1
- package/templates/reference-erc20/src/index.ts +7 -7
- package/templates/reference-erc4626/README.md +57 -0
- package/templates/reference-erc4626/_dot_env.local +5 -0
- package/templates/reference-erc4626/_dot_eslintrc.json +3 -0
- package/templates/reference-erc4626/_dot_gitignore +18 -0
- package/templates/reference-erc4626/abis/erc4626ABI.ts +341 -0
- package/templates/reference-erc4626/package.json +25 -0
- package/templates/reference-erc4626/ponder-env.d.ts +27 -0
- package/templates/reference-erc4626/ponder.config.ts +21 -0
- package/templates/reference-erc4626/ponder.schema.ts +62 -0
- package/templates/reference-erc4626/src/index.ts +95 -0
- package/templates/reference-erc4626/tsconfig.json +26 -0
- package/templates/reference-erc721/README.md +1 -1
- package/templates/reference-erc721/abis/erc721ABI.ts +165 -0
- package/templates/reference-erc721/package.json +0 -1
- package/templates/reference-erc721/ponder.config.ts +1 -1
- package/templates/reference-erc721/src/index.ts +2 -2
package/dist/index.js
CHANGED
|
@@ -16,7 +16,7 @@ import { default as prompts } from "prompts";
|
|
|
16
16
|
// package.json
|
|
17
17
|
var package_default = {
|
|
18
18
|
name: "create-ponder",
|
|
19
|
-
version: "0.2.
|
|
19
|
+
version: "0.2.10",
|
|
20
20
|
type: "module",
|
|
21
21
|
description: "A CLI tool to create Ponder apps",
|
|
22
22
|
license: "MIT",
|
|
@@ -652,6 +652,16 @@ var templates = [
|
|
|
652
652
|
id: "reference-erc721",
|
|
653
653
|
title: "Reference - ERC721",
|
|
654
654
|
description: "A Ponder app for an ERC721 token"
|
|
655
|
+
},
|
|
656
|
+
{
|
|
657
|
+
id: "reference-erc1155",
|
|
658
|
+
title: "Reference - ERC1155",
|
|
659
|
+
description: "A Ponder app for an ERC1155 token"
|
|
660
|
+
},
|
|
661
|
+
{
|
|
662
|
+
id: "reference-erc4626",
|
|
663
|
+
title: "Reference - ERC4626",
|
|
664
|
+
description: "A Ponder app for an ERC4626 token"
|
|
655
665
|
}
|
|
656
666
|
];
|
|
657
667
|
async function run({
|
package/package.json
CHANGED
|
@@ -4,6 +4,9 @@ PONDER_RPC_URL_1=
|
|
|
4
4
|
# Optimism RPC URL used for fetching blockchain data. Alchemy is recommended.
|
|
5
5
|
PONDER_RPC_URL_10=https://opt-mainnet.g.alchemy.com/v2/...
|
|
6
6
|
|
|
7
|
+
# Polygon RPC URL used for fetching blockchain data. Alchemy is recommended.
|
|
8
|
+
PONDER_RPC_URL_137=https://polygon-mainnet.g.alchemy.com/v2/...
|
|
9
|
+
|
|
7
10
|
# Base RPC URL used for fetching blockchain data. Alchemy is recommended.
|
|
8
11
|
PONDER_RPC_URL_8453=https://base-mainnet.g.alchemy.com/v2/...
|
|
9
12
|
|
|
@@ -15,24 +15,38 @@ const latestBlockOptimism = await createPublicClient({
|
|
|
15
15
|
const latestBlockArbitrum = await createPublicClient({
|
|
16
16
|
transport: http(process.env.PONDER_RPC_URL_42161),
|
|
17
17
|
}).getBlock();
|
|
18
|
+
const latestBlockPolygon = await createPublicClient({
|
|
19
|
+
transport: http(process.env.PONDER_RPC_URL_137),
|
|
20
|
+
}).getBlock();
|
|
21
|
+
|
|
22
|
+
console.log(latestBlockPolygon.number);
|
|
18
23
|
|
|
19
24
|
export default createConfig({
|
|
20
25
|
networks: {
|
|
21
26
|
mainnet: {
|
|
22
27
|
chainId: 1,
|
|
23
28
|
transport: http(process.env.PONDER_RPC_URL_1),
|
|
29
|
+
pollingInterval: 15_000,
|
|
24
30
|
},
|
|
25
31
|
base: {
|
|
26
32
|
chainId: 8453,
|
|
27
33
|
transport: http(process.env.PONDER_RPC_URL_8453),
|
|
34
|
+
pollingInterval: 15_000,
|
|
28
35
|
},
|
|
29
36
|
optimism: {
|
|
30
37
|
chainId: 10,
|
|
31
38
|
transport: http(process.env.PONDER_RPC_URL_10),
|
|
39
|
+
pollingInterval: 15_000,
|
|
32
40
|
},
|
|
33
41
|
arbitrum: {
|
|
34
42
|
chainId: 42161,
|
|
35
43
|
transport: http(process.env.PONDER_RPC_URL_42161),
|
|
44
|
+
pollingInterval: 15_000,
|
|
45
|
+
},
|
|
46
|
+
polygon: {
|
|
47
|
+
chainId: 137,
|
|
48
|
+
transport: http(process.env.PONDER_RPC_URL_137),
|
|
49
|
+
pollingInterval: 15_000,
|
|
36
50
|
},
|
|
37
51
|
},
|
|
38
52
|
contracts: {
|
|
@@ -54,6 +68,10 @@ export default createConfig({
|
|
|
54
68
|
address: "0x82aF49447D8a07e3bd95BD0d56f35241523fBab1",
|
|
55
69
|
startBlock: Number(latestBlockArbitrum.number) - 50,
|
|
56
70
|
},
|
|
71
|
+
polygon: {
|
|
72
|
+
address: "0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619",
|
|
73
|
+
startBlock: Number(latestBlockPolygon.number) - 200,
|
|
74
|
+
},
|
|
57
75
|
},
|
|
58
76
|
},
|
|
59
77
|
},
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Example ERC1155 token API
|
|
2
|
+
|
|
3
|
+
This example shows how to create a GraphQL API for an ERC1155 token using Ponder. It uses the Curio Cards Tokens contract on Ethereum ([Link](https://etherscan.io/address/0x73da73ef3a6982109c4d5bdb0db9dd3e3783f313)).
|
|
4
|
+
|
|
5
|
+
## Sample query
|
|
6
|
+
|
|
7
|
+
### Get the current owner and all transfer events for a token
|
|
8
|
+
|
|
9
|
+
```graphql
|
|
10
|
+
{
|
|
11
|
+
token(id: "7") {
|
|
12
|
+
account {
|
|
13
|
+
id
|
|
14
|
+
}
|
|
15
|
+
transferEvents {
|
|
16
|
+
items {
|
|
17
|
+
fromId
|
|
18
|
+
toId
|
|
19
|
+
timestamp
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
```
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
export const erc1155ABI = [
|
|
2
|
+
{
|
|
3
|
+
stateMutability: "view",
|
|
4
|
+
type: "function",
|
|
5
|
+
inputs: [
|
|
6
|
+
{ name: "", internalType: "address", type: "address" },
|
|
7
|
+
{ name: "", internalType: "uint256", type: "uint256" },
|
|
8
|
+
],
|
|
9
|
+
name: "balanceOf",
|
|
10
|
+
outputs: [{ name: "", internalType: "uint256", type: "uint256" }],
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
stateMutability: "view",
|
|
14
|
+
type: "function",
|
|
15
|
+
inputs: [
|
|
16
|
+
{ name: "owners", internalType: "address[]", type: "address[]" },
|
|
17
|
+
{ name: "ids", internalType: "uint256[]", type: "uint256[]" },
|
|
18
|
+
],
|
|
19
|
+
name: "balanceOfBatch",
|
|
20
|
+
outputs: [
|
|
21
|
+
{ name: "balances", internalType: "uint256[]", type: "uint256[]" },
|
|
22
|
+
],
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
stateMutability: "view",
|
|
26
|
+
type: "function",
|
|
27
|
+
inputs: [
|
|
28
|
+
{ name: "", internalType: "address", type: "address" },
|
|
29
|
+
{ name: "", internalType: "address", type: "address" },
|
|
30
|
+
],
|
|
31
|
+
name: "isApprovedForAll",
|
|
32
|
+
outputs: [{ name: "", internalType: "bool", type: "bool" }],
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
stateMutability: "nonpayable",
|
|
36
|
+
type: "function",
|
|
37
|
+
inputs: [
|
|
38
|
+
{ name: "from", internalType: "address", type: "address" },
|
|
39
|
+
{ name: "to", internalType: "address", type: "address" },
|
|
40
|
+
{ name: "ids", internalType: "uint256[]", type: "uint256[]" },
|
|
41
|
+
{ name: "amounts", internalType: "uint256[]", type: "uint256[]" },
|
|
42
|
+
{ name: "data", internalType: "bytes", type: "bytes" },
|
|
43
|
+
],
|
|
44
|
+
name: "safeBatchTransferFrom",
|
|
45
|
+
outputs: [],
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
stateMutability: "nonpayable",
|
|
49
|
+
type: "function",
|
|
50
|
+
inputs: [
|
|
51
|
+
{ name: "from", internalType: "address", type: "address" },
|
|
52
|
+
{ name: "to", internalType: "address", type: "address" },
|
|
53
|
+
{ name: "id", internalType: "uint256", type: "uint256" },
|
|
54
|
+
{ name: "amount", internalType: "uint256", type: "uint256" },
|
|
55
|
+
{ name: "data", internalType: "bytes", type: "bytes" },
|
|
56
|
+
],
|
|
57
|
+
name: "safeTransferFrom",
|
|
58
|
+
outputs: [],
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
stateMutability: "nonpayable",
|
|
62
|
+
type: "function",
|
|
63
|
+
inputs: [
|
|
64
|
+
{ name: "operator", internalType: "address", type: "address" },
|
|
65
|
+
{ name: "approved", internalType: "bool", type: "bool" },
|
|
66
|
+
],
|
|
67
|
+
name: "setApprovalForAll",
|
|
68
|
+
outputs: [],
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
stateMutability: "view",
|
|
72
|
+
type: "function",
|
|
73
|
+
inputs: [{ name: "interfaceId", internalType: "bytes4", type: "bytes4" }],
|
|
74
|
+
name: "supportsInterface",
|
|
75
|
+
outputs: [{ name: "", internalType: "bool", type: "bool" }],
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
stateMutability: "view",
|
|
79
|
+
type: "function",
|
|
80
|
+
inputs: [{ name: "id", internalType: "uint256", type: "uint256" }],
|
|
81
|
+
name: "uri",
|
|
82
|
+
outputs: [{ name: "", internalType: "string", type: "string" }],
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
type: "event",
|
|
86
|
+
anonymous: false,
|
|
87
|
+
inputs: [
|
|
88
|
+
{
|
|
89
|
+
name: "owner",
|
|
90
|
+
internalType: "address",
|
|
91
|
+
type: "address",
|
|
92
|
+
indexed: true,
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
name: "operator",
|
|
96
|
+
internalType: "address",
|
|
97
|
+
type: "address",
|
|
98
|
+
indexed: true,
|
|
99
|
+
},
|
|
100
|
+
{ name: "approved", internalType: "bool", type: "bool", indexed: false },
|
|
101
|
+
],
|
|
102
|
+
name: "ApprovalForAll",
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
type: "event",
|
|
106
|
+
anonymous: false,
|
|
107
|
+
inputs: [
|
|
108
|
+
{
|
|
109
|
+
name: "operator",
|
|
110
|
+
internalType: "address",
|
|
111
|
+
type: "address",
|
|
112
|
+
indexed: true,
|
|
113
|
+
},
|
|
114
|
+
{ name: "from", internalType: "address", type: "address", indexed: true },
|
|
115
|
+
{ name: "to", internalType: "address", type: "address", indexed: true },
|
|
116
|
+
{
|
|
117
|
+
name: "ids",
|
|
118
|
+
internalType: "uint256[]",
|
|
119
|
+
type: "uint256[]",
|
|
120
|
+
indexed: false,
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
name: "amounts",
|
|
124
|
+
internalType: "uint256[]",
|
|
125
|
+
type: "uint256[]",
|
|
126
|
+
indexed: false,
|
|
127
|
+
},
|
|
128
|
+
],
|
|
129
|
+
name: "TransferBatch",
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
type: "event",
|
|
133
|
+
anonymous: false,
|
|
134
|
+
inputs: [
|
|
135
|
+
{
|
|
136
|
+
name: "operator",
|
|
137
|
+
internalType: "address",
|
|
138
|
+
type: "address",
|
|
139
|
+
indexed: true,
|
|
140
|
+
},
|
|
141
|
+
{ name: "from", internalType: "address", type: "address", indexed: true },
|
|
142
|
+
{ name: "to", internalType: "address", type: "address", indexed: true },
|
|
143
|
+
{ name: "id", internalType: "uint256", type: "uint256", indexed: false },
|
|
144
|
+
{
|
|
145
|
+
name: "amount",
|
|
146
|
+
internalType: "uint256",
|
|
147
|
+
type: "uint256",
|
|
148
|
+
indexed: false,
|
|
149
|
+
},
|
|
150
|
+
],
|
|
151
|
+
name: "TransferSingle",
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
type: "event",
|
|
155
|
+
anonymous: false,
|
|
156
|
+
inputs: [
|
|
157
|
+
{ name: "value", internalType: "string", type: "string", indexed: false },
|
|
158
|
+
{ name: "id", internalType: "uint256", type: "uint256", indexed: true },
|
|
159
|
+
],
|
|
160
|
+
name: "URI",
|
|
161
|
+
},
|
|
162
|
+
] as const;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "ponder-examples-reference-erc1155",
|
|
3
|
+
"private": true,
|
|
4
|
+
"type": "module",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"dev": "ponder dev",
|
|
7
|
+
"start": "ponder start",
|
|
8
|
+
"codegen": "ponder codegen",
|
|
9
|
+
"lint": "eslint .",
|
|
10
|
+
"typecheck": "tsc"
|
|
11
|
+
},
|
|
12
|
+
"dependencies": {
|
|
13
|
+
"@ponder/core": "workspace:*",
|
|
14
|
+
"viem": "^1.19.9"
|
|
15
|
+
},
|
|
16
|
+
"devDependencies": {
|
|
17
|
+
"@types/node": "^20.10.0",
|
|
18
|
+
"eslint": "^8.54.0",
|
|
19
|
+
"eslint-config-ponder": "workspace:*",
|
|
20
|
+
"typescript": "^5.3.2"
|
|
21
|
+
},
|
|
22
|
+
"engines": {
|
|
23
|
+
"node": ">=18.14"
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// This file enables type checking and editor autocomplete for this Ponder project.
|
|
2
|
+
// After upgrading, you may find that changes have been made to this file.
|
|
3
|
+
// If this happens, please commit the changes. Do not manually edit this file.
|
|
4
|
+
// See https://ponder.sh/docs/guides/typescript for more information.
|
|
5
|
+
|
|
6
|
+
declare module "@/generated" {
|
|
7
|
+
import type { Virtual } from "@ponder/core";
|
|
8
|
+
|
|
9
|
+
type config = typeof import("./ponder.config.ts").default;
|
|
10
|
+
type schema = typeof import("./ponder.schema.ts").default;
|
|
11
|
+
|
|
12
|
+
export const ponder: Virtual.Registry<config, schema>;
|
|
13
|
+
|
|
14
|
+
export type EventNames = Virtual.EventNames<config>;
|
|
15
|
+
export type Event<name extends EventNames = EventNames> = Virtual.Event<
|
|
16
|
+
config,
|
|
17
|
+
name
|
|
18
|
+
>;
|
|
19
|
+
export type Context<name extends EventNames = EventNames> = Virtual.Context<
|
|
20
|
+
config,
|
|
21
|
+
schema,
|
|
22
|
+
name
|
|
23
|
+
>;
|
|
24
|
+
export type IndexingFunctionArgs<name extends EventNames = EventNames> =
|
|
25
|
+
Virtual.IndexingFunctionArgs<config, schema, name>;
|
|
26
|
+
export type Schema = Virtual.Schema<schema>;
|
|
27
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { createConfig } from "@ponder/core";
|
|
2
|
+
import { http } from "viem";
|
|
3
|
+
import { erc1155ABI } from "./abis/erc1155Abi";
|
|
4
|
+
|
|
5
|
+
export default createConfig({
|
|
6
|
+
networks: {
|
|
7
|
+
mainnet: {
|
|
8
|
+
chainId: 1,
|
|
9
|
+
transport: http(process.env.PONDER_RPC_URL_1),
|
|
10
|
+
},
|
|
11
|
+
},
|
|
12
|
+
contracts: {
|
|
13
|
+
ERC1155: {
|
|
14
|
+
network: "mainnet",
|
|
15
|
+
abi: erc1155ABI,
|
|
16
|
+
address: "0x73da73ef3a6982109c4d5bdb0db9dd3e3783f313",
|
|
17
|
+
startBlock: 12129118,
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
});
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { createSchema } from "@ponder/core";
|
|
2
|
+
|
|
3
|
+
export default createSchema((p) => ({
|
|
4
|
+
Account: p.createTable({
|
|
5
|
+
id: p.hex(),
|
|
6
|
+
tokens: p.many("TokenBalance.ownerId"),
|
|
7
|
+
|
|
8
|
+
transferFromEvents: p.many("TransferEvent.fromId"),
|
|
9
|
+
transferToEvents: p.many("TransferEvent.toId"),
|
|
10
|
+
}),
|
|
11
|
+
TokenBalance: p.createTable({
|
|
12
|
+
id: p.string(),
|
|
13
|
+
tokenId: p.bigint(),
|
|
14
|
+
balance: p.bigint(),
|
|
15
|
+
|
|
16
|
+
ownerId: p.hex().references("Account.id"),
|
|
17
|
+
owner: p.one("ownerId"),
|
|
18
|
+
}),
|
|
19
|
+
TransferEvent: p.createTable({
|
|
20
|
+
id: p.string(),
|
|
21
|
+
timestamp: p.int(),
|
|
22
|
+
fromId: p.hex().references("Account.id"),
|
|
23
|
+
toId: p.hex().references("Account.id"),
|
|
24
|
+
tokenId: p.bigint(),
|
|
25
|
+
|
|
26
|
+
from: p.one("fromId"),
|
|
27
|
+
to: p.one("toId"),
|
|
28
|
+
}),
|
|
29
|
+
}));
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { ponder } from "@/generated";
|
|
2
|
+
|
|
3
|
+
ponder.on("ERC1155:TransferSingle", async ({ event, context }) => {
|
|
4
|
+
const { Account, TokenBalance, TransferEvent } = context.db;
|
|
5
|
+
|
|
6
|
+
// Create an Account for the sender, or update the balance if it already exists.
|
|
7
|
+
await Account.upsert({
|
|
8
|
+
id: event.args.from,
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
await TokenBalance.upsert({
|
|
12
|
+
id: `${event.args.id}-${event.args.from}`,
|
|
13
|
+
create: {
|
|
14
|
+
tokenId: event.args.id,
|
|
15
|
+
ownerId: event.args.from,
|
|
16
|
+
balance: -event.args.amount,
|
|
17
|
+
},
|
|
18
|
+
update: ({ current }) => ({
|
|
19
|
+
tokenId: event.args.id,
|
|
20
|
+
ownerId: event.args.from,
|
|
21
|
+
balance: current.balance - event.args.amount,
|
|
22
|
+
}),
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
// Create an Account for the recipient, or update the balance if it already exists.
|
|
26
|
+
await Account.upsert({
|
|
27
|
+
id: event.args.to,
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
await TokenBalance.upsert({
|
|
31
|
+
id: `${event.args.id}-${event.args.to}`,
|
|
32
|
+
create: {
|
|
33
|
+
tokenId: event.args.id,
|
|
34
|
+
ownerId: event.args.to,
|
|
35
|
+
balance: event.args.amount,
|
|
36
|
+
},
|
|
37
|
+
update: ({ current }) => ({
|
|
38
|
+
tokenId: event.args.id,
|
|
39
|
+
ownerId: event.args.to,
|
|
40
|
+
balance: current.balance + event.args.amount,
|
|
41
|
+
}),
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
// Create a TransferEvent.
|
|
45
|
+
await TransferEvent.create({
|
|
46
|
+
id: event.log.id,
|
|
47
|
+
data: {
|
|
48
|
+
fromId: event.args.from,
|
|
49
|
+
toId: event.args.to,
|
|
50
|
+
tokenId: event.args.id,
|
|
51
|
+
timestamp: Number(event.block.timestamp),
|
|
52
|
+
},
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
ponder.on("ERC1155:TransferBatch", async ({ event, context }) => {
|
|
57
|
+
const { Account, TokenBalance, TransferEvent } = context.db;
|
|
58
|
+
|
|
59
|
+
await Account.upsert({
|
|
60
|
+
id: event.args.from,
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
await Account.upsert({
|
|
64
|
+
id: event.args.to,
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
for (let i = 0; i < event.args.ids.length; i++) {
|
|
68
|
+
const id = event.args.ids[i]!;
|
|
69
|
+
const amount = event.args.amounts[i]!;
|
|
70
|
+
|
|
71
|
+
await TokenBalance.upsert({
|
|
72
|
+
id: `${id}-${event.args.from}`,
|
|
73
|
+
create: {
|
|
74
|
+
tokenId: id,
|
|
75
|
+
ownerId: event.args.from,
|
|
76
|
+
balance: -amount,
|
|
77
|
+
},
|
|
78
|
+
update: ({ current }) => ({
|
|
79
|
+
tokenId: id,
|
|
80
|
+
ownerId: event.args.from,
|
|
81
|
+
balance: current.balance - amount,
|
|
82
|
+
}),
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
await TokenBalance.upsert({
|
|
86
|
+
id: `${id}-${event.args.to}`,
|
|
87
|
+
create: {
|
|
88
|
+
tokenId: id,
|
|
89
|
+
ownerId: event.args.to,
|
|
90
|
+
balance: amount,
|
|
91
|
+
},
|
|
92
|
+
update: ({ current }) => ({
|
|
93
|
+
tokenId: id,
|
|
94
|
+
ownerId: event.args.to,
|
|
95
|
+
balance: current.balance + amount,
|
|
96
|
+
}),
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
await TransferEvent.create({
|
|
100
|
+
id: `${event.log.id}-${i}`,
|
|
101
|
+
data: {
|
|
102
|
+
fromId: event.args.from,
|
|
103
|
+
toId: event.args.to,
|
|
104
|
+
tokenId: id,
|
|
105
|
+
timestamp: Number(event.block.timestamp),
|
|
106
|
+
},
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
});
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
// Type checking
|
|
4
|
+
"strict": true,
|
|
5
|
+
"noUncheckedIndexedAccess": true,
|
|
6
|
+
|
|
7
|
+
// Interop constraints
|
|
8
|
+
"verbatimModuleSyntax": false,
|
|
9
|
+
"esModuleInterop": true,
|
|
10
|
+
"isolatedModules": true,
|
|
11
|
+
"allowSyntheticDefaultImports": true,
|
|
12
|
+
"resolveJsonModule": true,
|
|
13
|
+
|
|
14
|
+
// Language and environment
|
|
15
|
+
"moduleResolution": "bundler",
|
|
16
|
+
"module": "ESNext",
|
|
17
|
+
"noEmit": true,
|
|
18
|
+
"lib": ["ES2022"],
|
|
19
|
+
"target": "ES2022",
|
|
20
|
+
|
|
21
|
+
// Skip type checking for node modules
|
|
22
|
+
"skipLibCheck": true
|
|
23
|
+
},
|
|
24
|
+
"include": ["./**/*.ts"],
|
|
25
|
+
"exclude": ["node_modules"]
|
|
26
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Example ERC20 token API
|
|
2
2
|
|
|
3
|
-
This example shows how to create a GraphQL API for an ERC20 token using Ponder. It uses the Adventure Gold token contract.
|
|
3
|
+
This example shows how to create a GraphQL API for an ERC20 token using Ponder. It uses the Adventure Gold token contract on Ethereum ([Link](https://etherscan.io/address/0x32353A6C91143bfd6C7d363B546e62a9A2489A20)).
|
|
4
4
|
|
|
5
5
|
## Sample queries
|
|
6
6
|
|