@solana/rpc-graphql 2.0.0-experimental.fe07532 → 2.0.0-experimental.feaeef2
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/README.md +1088 -30
- package/dist/index.browser.cjs +3145 -1974
- package/dist/index.browser.cjs.map +1 -1
- package/dist/index.browser.js +3142 -1976
- package/dist/index.browser.js.map +1 -1
- package/dist/index.native.js +3142 -1972
- package/dist/index.native.js.map +1 -1
- package/dist/index.node.cjs +3145 -1970
- package/dist/index.node.cjs.map +1 -1
- package/dist/index.node.js +3142 -1972
- package/dist/index.node.js.map +1 -1
- package/dist/types/context.d.ts +16 -19
- package/dist/types/context.d.ts.map +1 -1
- package/dist/types/index.d.ts +6 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/loaders/account.d.ts +14 -0
- package/dist/types/loaders/account.d.ts.map +1 -0
- package/dist/types/loaders/block.d.ts +4 -0
- package/dist/types/loaders/block.d.ts.map +1 -0
- package/dist/types/loaders/coalescer.d.ts +55 -0
- package/dist/types/loaders/coalescer.d.ts.map +1 -0
- package/dist/types/loaders/index.d.ts +6 -0
- package/dist/types/loaders/index.d.ts.map +1 -0
- package/dist/types/loaders/loader.d.ts +82 -0
- package/dist/types/loaders/loader.d.ts.map +1 -0
- package/dist/types/loaders/program-accounts.d.ts +8 -0
- package/dist/types/loaders/program-accounts.d.ts.map +1 -0
- package/dist/types/loaders/transaction.d.ts +4 -0
- package/dist/types/loaders/transaction.d.ts.map +1 -0
- package/dist/types/resolvers/account.d.ts +232 -0
- package/dist/types/resolvers/account.d.ts.map +1 -0
- package/dist/types/resolvers/block.d.ts +104 -0
- package/dist/types/resolvers/block.d.ts.map +1 -0
- package/dist/types/resolvers/index.d.ts +3 -0
- package/dist/types/resolvers/index.d.ts.map +1 -0
- package/dist/types/resolvers/instruction.d.ts +2220 -0
- package/dist/types/resolvers/instruction.d.ts.map +1 -0
- package/dist/types/resolvers/program-accounts.d.ts +19 -0
- package/dist/types/resolvers/program-accounts.d.ts.map +1 -0
- package/dist/types/resolvers/resolve-info/account.d.ts +15 -0
- package/dist/types/resolvers/resolve-info/account.d.ts.map +1 -0
- package/dist/types/resolvers/resolve-info/block.d.ts +13 -0
- package/dist/types/resolvers/resolve-info/block.d.ts.map +1 -0
- package/dist/types/resolvers/resolve-info/index.d.ts +6 -0
- package/dist/types/resolvers/resolve-info/index.d.ts.map +1 -0
- package/dist/types/resolvers/resolve-info/program-accounts.d.ts +20 -0
- package/dist/types/resolvers/resolve-info/program-accounts.d.ts.map +1 -0
- package/dist/types/resolvers/resolve-info/transaction.d.ts +15 -0
- package/dist/types/resolvers/resolve-info/transaction.d.ts.map +1 -0
- package/dist/types/resolvers/resolve-info/visitor.d.ts +18 -0
- package/dist/types/resolvers/resolve-info/visitor.d.ts.map +1 -0
- package/dist/types/resolvers/root.d.ts +3 -0
- package/dist/types/resolvers/root.d.ts.map +1 -0
- package/dist/types/resolvers/transaction.d.ts +42 -0
- package/dist/types/resolvers/transaction.d.ts.map +1 -0
- package/dist/types/resolvers/types.d.ts +94 -0
- package/dist/types/resolvers/types.d.ts.map +1 -0
- package/dist/types/schema/account.d.ts +2 -0
- package/dist/types/schema/account.d.ts.map +1 -0
- package/dist/types/schema/block.d.ts +2 -0
- package/dist/types/schema/block.d.ts.map +1 -0
- package/dist/types/schema/index.d.ts +2 -0
- package/dist/types/schema/index.d.ts.map +1 -0
- package/dist/types/schema/instruction.d.ts +2 -0
- package/dist/types/schema/instruction.d.ts.map +1 -0
- package/dist/types/schema/root.d.ts +2 -0
- package/dist/types/schema/root.d.ts.map +1 -0
- package/dist/types/schema/transaction.d.ts +2 -0
- package/dist/types/schema/transaction.d.ts.map +1 -0
- package/dist/types/schema/types.d.ts +2 -0
- package/dist/types/schema/types.d.ts.map +1 -0
- package/package.json +14 -37
- package/dist/types/cache.d.ts +0 -7
- package/dist/types/cache.d.ts.map +0 -1
- package/dist/types/rpc.d.ts +0 -13
- package/dist/types/rpc.d.ts.map +0 -1
- package/dist/types/schema/account/index.d.ts +0 -3
- package/dist/types/schema/account/index.d.ts.map +0 -1
- package/dist/types/schema/account/query.d.ts +0 -38
- package/dist/types/schema/account/query.d.ts.map +0 -1
- package/dist/types/schema/account/types.d.ts +0 -5
- package/dist/types/schema/account/types.d.ts.map +0 -1
- package/dist/types/schema/block/index.d.ts +0 -3
- package/dist/types/schema/block/index.d.ts.map +0 -1
- package/dist/types/schema/block/query.d.ts +0 -42
- package/dist/types/schema/block/query.d.ts.map +0 -1
- package/dist/types/schema/block/types.d.ts +0 -7
- package/dist/types/schema/block/types.d.ts.map +0 -1
- package/dist/types/schema/inputs.d.ts +0 -9
- package/dist/types/schema/inputs.d.ts.map +0 -1
- package/dist/types/schema/picks.d.ts +0 -36
- package/dist/types/schema/picks.d.ts.map +0 -1
- package/dist/types/schema/program-accounts/index.d.ts +0 -2
- package/dist/types/schema/program-accounts/index.d.ts.map +0 -1
- package/dist/types/schema/program-accounts/query.d.ts +0 -47
- package/dist/types/schema/program-accounts/query.d.ts.map +0 -1
- package/dist/types/schema/program-accounts/types.d.ts +0 -3
- package/dist/types/schema/program-accounts/types.d.ts.map +0 -1
- package/dist/types/schema/scalars.d.ts +0 -3
- package/dist/types/schema/scalars.d.ts.map +0 -1
- package/dist/types/schema/transaction/index.d.ts +0 -3
- package/dist/types/schema/transaction/index.d.ts.map +0 -1
- package/dist/types/schema/transaction/query.d.ts +0 -33
- package/dist/types/schema/transaction/query.d.ts.map +0 -1
- package/dist/types/schema/transaction/types.d.ts +0 -12
- package/dist/types/schema/transaction/types.d.ts.map +0 -1
package/README.md
CHANGED
|
@@ -3,61 +3,1119 @@
|
|
|
3
3
|
This package defines a GraphQL client resolver built on top of the
|
|
4
4
|
[Solana JSON-RPC](https://docs.solana.com/api/http).
|
|
5
5
|
|
|
6
|
-
# Solana & GraphQL
|
|
7
|
-
|
|
8
6
|
GraphQL is a query language for your API, and a server-side runtime for
|
|
9
7
|
executing queries using a type system you define for your data.
|
|
10
8
|
|
|
11
9
|
<img src="https://upload.wikimedia.org/wikipedia/commons/thumb/1/17/GraphQL_Logo.svg/1024px-GraphQL_Logo.svg.png?20161105194737" alt="graphql-icon" width="24" align="center"/> [**GraphQL**](https://graphql.org/learn/)
|
|
12
10
|
|
|
13
|
-
This library attempts to define a type
|
|
14
|
-
type
|
|
11
|
+
This library attempts to define a type schema for Solana. With the proper
|
|
12
|
+
type schema, developers can take advantage of the best features of GraphQL
|
|
15
13
|
to make interacting with Solana via RPC smoother, faster, more reliable,
|
|
16
14
|
and involve less code.
|
|
17
15
|
|
|
18
|
-
|
|
16
|
+
# Design
|
|
17
|
+
|
|
18
|
+
On-chain data can be categorized into three main types:
|
|
19
|
+
|
|
20
|
+
- Accounts
|
|
21
|
+
- Transactions
|
|
22
|
+
- Blocks
|
|
23
|
+
|
|
24
|
+
These types encompass everything that can be queried from the Solana ledger.
|
|
25
|
+
|
|
26
|
+
The Solana RPC provides a parsing method known as `jsonParsed` for supported
|
|
27
|
+
types, such as accounts and transaction instructions.
|
|
28
|
+
|
|
29
|
+
This library leverages GraphQL **interfaces** for each of these types paired
|
|
30
|
+
with specific GraphQL types for each `jsonParsed` object. This allows for
|
|
31
|
+
powerful querying of `jsonParsed` data, including nested and chained queries!
|
|
32
|
+
|
|
33
|
+
## Setting up a GraphQL RPC Client
|
|
34
|
+
|
|
35
|
+
Initializing an RPC-GraphQL using `@solana/rpc-graphql` requires an RPC client,
|
|
36
|
+
either built using `@solana/web3.js` or it's child libraries `@solana/rpc-core`
|
|
37
|
+
and `@solana/rpc-transport`.
|
|
38
|
+
|
|
39
|
+
```typescript
|
|
40
|
+
import { createSolanaRpc, createDefaultRpcTransport } from '@solana/web3.js';
|
|
41
|
+
import { createRpcGraphQL } from '@solana/rpc-graphql';
|
|
42
|
+
|
|
43
|
+
// Set up an HTTP transport
|
|
44
|
+
const transport = createDefaultRpcTransport({ url: 'http://127.0.0.1:8899' });
|
|
45
|
+
|
|
46
|
+
// Create the RPC client
|
|
47
|
+
const rpc = createSolanaRpc({ transport });
|
|
48
|
+
|
|
49
|
+
// Create the RPC-GraphQL client
|
|
50
|
+
const rpcGraphQL = createRpcGraphQL(rpc);
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
The `RpcGraphQL` type supports one method `query(..)` which accepts a string
|
|
54
|
+
query source and an optional `variableValues` parameter - which is an object
|
|
55
|
+
containing any variables to pipe into the query string.
|
|
56
|
+
|
|
57
|
+
You can define queries with hard-coded parameters.
|
|
58
|
+
|
|
59
|
+
```typescript
|
|
60
|
+
const source = `
|
|
61
|
+
query myQuery {
|
|
62
|
+
account(address: "AyGCwnwxQMCqaU4ixReHt8h5W4dwmxU7eM3BEQBdWVca") {
|
|
63
|
+
lamports
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
`;
|
|
67
|
+
|
|
68
|
+
const result = await rpcGraphQL.query(source);
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
```
|
|
72
|
+
data: {
|
|
73
|
+
account: {
|
|
74
|
+
lamports: 10290815n,
|
|
75
|
+
},
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
You can also pass the variable values.
|
|
80
|
+
|
|
81
|
+
```typescript
|
|
82
|
+
const source = `
|
|
83
|
+
query myQuery($address: String!) {
|
|
84
|
+
account(address: $address) {
|
|
85
|
+
lamports
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
`;
|
|
89
|
+
|
|
90
|
+
const variableValues = {
|
|
91
|
+
address: 'AyGCwnwxQMCqaU4ixReHt8h5W4dwmxU7eM3BEQBdWVca',
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
const result = await rpcGraphQL.query(source, variableValues);
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
```
|
|
98
|
+
data: {
|
|
99
|
+
account: {
|
|
100
|
+
lamports: 10290815n,
|
|
101
|
+
},
|
|
102
|
+
}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Queries with variable values can also be re-used!
|
|
106
|
+
|
|
107
|
+
```typescript
|
|
108
|
+
const source = `
|
|
109
|
+
query myQuery($address: String!) {
|
|
110
|
+
account(address: $address) {
|
|
111
|
+
lamports
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
`;
|
|
115
|
+
|
|
116
|
+
const lamportsAccountA = await rpcGraphQL.query(source, {
|
|
117
|
+
address: 'AyGCwnwxQMCqaU4ixReHt8h5W4dwmxU7eM3BEQBdWVca',
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
const lamportsAccountB = await rpcGraphQL.query(source, {
|
|
121
|
+
address: 'CcYNb7WqpjaMrNr7B1mapaNfWctZRH7LyAjWRLBGt1Fk',
|
|
122
|
+
});
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## Querying Accounts
|
|
126
|
+
|
|
127
|
+
The `Account` interface contains common fields across all accounts.
|
|
128
|
+
|
|
129
|
+
`src/schema/account/types.ts: AccountInterface`
|
|
130
|
+
|
|
131
|
+
```graphql
|
|
132
|
+
interface Account {
|
|
133
|
+
address: String
|
|
134
|
+
encoding: String
|
|
135
|
+
executable: Boolean
|
|
136
|
+
lamports: BigInt
|
|
137
|
+
owner: Account
|
|
138
|
+
rentEpoch: BigInt
|
|
139
|
+
}
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
Any account can be queried by these fields without specifying the specific
|
|
143
|
+
account type.
|
|
144
|
+
|
|
145
|
+
```typescript
|
|
146
|
+
const source = `
|
|
147
|
+
query myQuery($address: String!) {
|
|
148
|
+
account(address: $address) {
|
|
149
|
+
executable
|
|
150
|
+
lamports
|
|
151
|
+
rentEpoch
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
`;
|
|
155
|
+
|
|
156
|
+
const variableValues = {
|
|
157
|
+
address: 'AyGCwnwxQMCqaU4ixReHt8h5W4dwmxU7eM3BEQBdWVca',
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
const result = await rpcGraphQL.query(source, variableValues);
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
```
|
|
164
|
+
data: {
|
|
165
|
+
account: {
|
|
166
|
+
executable: false,
|
|
167
|
+
lamports: 10290815n,
|
|
168
|
+
rentEpoch: 0n,
|
|
169
|
+
},
|
|
170
|
+
}
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
### Specific Account Types
|
|
174
|
+
|
|
175
|
+
Each `jsonParsed` account type has its own GraphQL type that can be used in a
|
|
176
|
+
GraphQL query.
|
|
177
|
+
|
|
178
|
+
- `AccountBase58`: A Solana account with base58 encoded data
|
|
179
|
+
- `AccountBase64`: A Solana account with base64 encoded data
|
|
180
|
+
- `AccountBase64Zstd`: A Solana account with base64 encoded data compressed with zstd
|
|
181
|
+
- `NonceAccount`: A nonce account
|
|
182
|
+
- `LookupTableAccount`: An address lookup table account
|
|
183
|
+
- `MintAccount`: An SPL mint
|
|
184
|
+
- `TokenAccount`: An SPL token account
|
|
185
|
+
- `StakeAccount`: A stake account
|
|
186
|
+
- `VoteAccount`: A vote account
|
|
187
|
+
|
|
188
|
+
You can choose how to handle querying of specific account types. For example,
|
|
189
|
+
you might _only_ want specifically any account that matches `MintAccount`.
|
|
190
|
+
|
|
191
|
+
```typescript
|
|
192
|
+
const maybeMintAddresses = [
|
|
193
|
+
'J7iup799j5BVjKXACZycYef7WQ4x1wfzhUsc5v357yWQ',
|
|
194
|
+
'JAbWqZ7S2c6jomQr8ofAYBo257bE1QJtHwbX1yWc2osZ',
|
|
195
|
+
'2AQ4CSNu6zNUZsUq4aLNUSjyrLv4qFFXQuKs5RTHbg2Y',
|
|
196
|
+
'EVW3CoyogapBfQxBFFEKGMM1bn3JyoFiqkAJdw3FHX1b',
|
|
197
|
+
];
|
|
198
|
+
|
|
199
|
+
const mintAccounts = [];
|
|
200
|
+
|
|
201
|
+
const source = `
|
|
202
|
+
query myQuery($address: String!) {
|
|
203
|
+
account(address: $address) {
|
|
204
|
+
... on MintAccount {
|
|
205
|
+
data {
|
|
206
|
+
decimals
|
|
207
|
+
isInitialized
|
|
208
|
+
mintAuthority
|
|
209
|
+
supply
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
`;
|
|
215
|
+
|
|
216
|
+
for (const address of maybeMintAddresses) {
|
|
217
|
+
const result = await rpcGraphQL.query(source, { address });
|
|
218
|
+
if (result != null) {
|
|
219
|
+
const {
|
|
220
|
+
data: {
|
|
221
|
+
account: {
|
|
222
|
+
data: mintInfo,
|
|
223
|
+
},
|
|
224
|
+
},
|
|
225
|
+
} = result;
|
|
226
|
+
mintAccounts.push(mintInfo);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
Maybe you want to handle both mints _and_ token accounts.
|
|
232
|
+
|
|
233
|
+
```typescript
|
|
234
|
+
const mintOrTokenAccountAddresses = [
|
|
235
|
+
'J7iup799j5BVjKXACZycYef7WQ4x1wfzhUsc5v357yWQ',
|
|
236
|
+
'JAbWqZ7S2c6jomQr8ofAYBo257bE1QJtHwbX1yWc2osZ',
|
|
237
|
+
'2AQ4CSNu6zNUZsUq4aLNUSjyrLv4qFFXQuKs5RTHbg2Y',
|
|
238
|
+
'EVW3CoyogapBfQxBFFEKGMM1bn3JyoFiqkAJdw3FHX1b',
|
|
239
|
+
];
|
|
240
|
+
|
|
241
|
+
const mintAccounts = [];
|
|
242
|
+
const tokenAccounts = [];
|
|
243
|
+
|
|
244
|
+
const source = `
|
|
245
|
+
query myQuery($address: String!) {
|
|
246
|
+
account(address: $address) {
|
|
247
|
+
... on MintAccount {
|
|
248
|
+
data {
|
|
249
|
+
decimals
|
|
250
|
+
isInitialized
|
|
251
|
+
supply
|
|
252
|
+
}
|
|
253
|
+
meta {
|
|
254
|
+
type
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
... on TokenAccount {
|
|
258
|
+
data {
|
|
259
|
+
isNative
|
|
260
|
+
mint
|
|
261
|
+
state
|
|
262
|
+
}
|
|
263
|
+
meta {
|
|
264
|
+
type
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
`;
|
|
270
|
+
|
|
271
|
+
for (const address of mintOrTokenAccountAddresses) {
|
|
272
|
+
const result = await rpcGraphQL.query(source, { address });
|
|
273
|
+
if (result != null) {
|
|
274
|
+
const {
|
|
275
|
+
data: {
|
|
276
|
+
account: {
|
|
277
|
+
data: accountParsedInfo,
|
|
278
|
+
meta: {
|
|
279
|
+
type: accountType,
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
} = result;
|
|
284
|
+
if (accountType === 'mint') {
|
|
285
|
+
mintAccounts.push(accountParsedInfo)
|
|
286
|
+
} else {
|
|
287
|
+
tokenAccounts.push(accountParsedInfo)
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
Querying accounts by their encoded data (`base58`, `base64`, `base64+zstd`) is
|
|
294
|
+
still fully supported.
|
|
295
|
+
|
|
296
|
+
```typescript
|
|
297
|
+
const source = `
|
|
298
|
+
query myQuery($address: String!, $encoding: AccountEncoding) {
|
|
299
|
+
account(address: $address, encoding: $encoding) {
|
|
300
|
+
... on AccountBase64 {
|
|
301
|
+
data
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
`;
|
|
306
|
+
|
|
307
|
+
const variableValues = {
|
|
308
|
+
address: 'CcYNb7WqpjaMrNr7B1mapaNfWctZRH7LyAjWRLBGt1Fk',
|
|
309
|
+
encoding: 'base64',
|
|
310
|
+
};
|
|
311
|
+
|
|
312
|
+
const result = await rpcGraphQL.query(source, variableValues);
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
```
|
|
316
|
+
data: {
|
|
317
|
+
account: {
|
|
318
|
+
data: 'dGVzdCBkYXRh',
|
|
319
|
+
},
|
|
320
|
+
}
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
### Nested Account Queries
|
|
324
|
+
|
|
325
|
+
Notice the `owner` field of the `Account` interface is also an `Account`
|
|
326
|
+
interface. This powers nested queries against the `owner` field of an account.
|
|
327
|
+
|
|
328
|
+
```typescript
|
|
329
|
+
const source = `
|
|
330
|
+
query myQuery($address: String!) {
|
|
331
|
+
account(address: $address) {
|
|
332
|
+
address
|
|
333
|
+
owner {
|
|
334
|
+
address
|
|
335
|
+
executable
|
|
336
|
+
lamports
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
`;
|
|
341
|
+
|
|
342
|
+
const variableValues = {
|
|
343
|
+
address: 'AyGCwnwxQMCqaU4ixReHt8h5W4dwmxU7eM3BEQBdWVca',
|
|
344
|
+
};
|
|
345
|
+
|
|
346
|
+
const result = await rpcGraphQL.query(source, variableValues);
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
```
|
|
350
|
+
data: {
|
|
351
|
+
account: {
|
|
352
|
+
address: 'AyGCwnwxQMCqaU4ixReHt8h5W4dwmxU7eM3BEQBdWVca',
|
|
353
|
+
owner: {
|
|
354
|
+
address: 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA',
|
|
355
|
+
executable: true,
|
|
356
|
+
lamports: 10290815n,
|
|
357
|
+
},
|
|
358
|
+
},
|
|
359
|
+
}
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
As you can see, simply defining a nested query with RPC-GraphQL will augment
|
|
363
|
+
the multiple RPC calls and parsing code required to gather the necessary
|
|
364
|
+
information!
|
|
365
|
+
|
|
366
|
+
You can nest queries as far as you want!
|
|
367
|
+
|
|
368
|
+
```typescript
|
|
369
|
+
const source = `
|
|
370
|
+
query myQuery($address: String!) {
|
|
371
|
+
account(address: $address) {
|
|
372
|
+
address
|
|
373
|
+
owner {
|
|
374
|
+
address
|
|
375
|
+
owner {
|
|
376
|
+
address
|
|
377
|
+
owner {
|
|
378
|
+
address
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
`;
|
|
385
|
+
|
|
386
|
+
const variableValues = {
|
|
387
|
+
address: 'AyGCwnwxQMCqaU4ixReHt8h5W4dwmxU7eM3BEQBdWVca',
|
|
388
|
+
};
|
|
389
|
+
|
|
390
|
+
const result = await rpcGraphQL.query(source, variableValues);
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
```
|
|
394
|
+
data: {
|
|
395
|
+
account: {
|
|
396
|
+
address: 'AyGCwnwxQMCqaU4ixReHt8h5W4dwmxU7eM3BEQBdWVca',
|
|
397
|
+
owner: {
|
|
398
|
+
address: 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA',
|
|
399
|
+
owner: {
|
|
400
|
+
address: 'BPFLoader2111111111111111111111111111111111',
|
|
401
|
+
owner: {
|
|
402
|
+
address: 'NativeLoader1111111111111111111111111111111',
|
|
403
|
+
},
|
|
404
|
+
},
|
|
405
|
+
},
|
|
406
|
+
},
|
|
407
|
+
}
|
|
408
|
+
```
|
|
409
|
+
|
|
410
|
+
Nested queries can also be applied to specific account types.
|
|
411
|
+
|
|
412
|
+
```typescript
|
|
413
|
+
const source = `
|
|
414
|
+
query myQuery($address: String!) {
|
|
415
|
+
account(address: $address) {
|
|
416
|
+
... on MintAccount {
|
|
417
|
+
address
|
|
418
|
+
data {
|
|
419
|
+
mintAuthority {
|
|
420
|
+
address
|
|
421
|
+
lamports
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
`;
|
|
428
|
+
|
|
429
|
+
const variableValues = {
|
|
430
|
+
address: 'AyGCwnwxQMCqaU4ixReHt8h5W4dwmxU7eM3BEQBdWVca',
|
|
431
|
+
};
|
|
432
|
+
|
|
433
|
+
const result = await rpcGraphQL.query(source, variableValues);
|
|
434
|
+
```
|
|
435
|
+
|
|
436
|
+
```
|
|
437
|
+
data: {
|
|
438
|
+
account: {
|
|
439
|
+
address: 'AyGCwnwxQMCqaU4ixReHt8h5W4dwmxU7eM3BEQBdWVca',
|
|
440
|
+
data: {
|
|
441
|
+
mintAuthority: {
|
|
442
|
+
address: 'DpfJkNonoVB3sor9H9ceajhex4XHVPrDAGAq2ahdG4JZ',
|
|
443
|
+
lamports: 10290815n,
|
|
444
|
+
}
|
|
445
|
+
},
|
|
446
|
+
},
|
|
447
|
+
}
|
|
448
|
+
```
|
|
449
|
+
|
|
450
|
+
## Querying Program Accounts
|
|
451
|
+
|
|
452
|
+
A very common way to query Solana accounts from an RPC is to request all of
|
|
453
|
+
the accounts owned by a particular program.
|
|
454
|
+
|
|
455
|
+
With RPC-GraphQL, querying program-owned accounts is a list-based extension of
|
|
456
|
+
the account query defined previously. This means program accounts queries will
|
|
457
|
+
return a list of objects implementing the `Account` interface.
|
|
458
|
+
|
|
459
|
+
Setting up the query is very similar to the `account` query.
|
|
460
|
+
|
|
461
|
+
```typescript
|
|
462
|
+
const source = `
|
|
463
|
+
query myQuery($programAddress: String!) {
|
|
464
|
+
programAccounts(programAddress: $address) {
|
|
465
|
+
executable
|
|
466
|
+
lamports
|
|
467
|
+
rentEpoch
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
`;
|
|
471
|
+
|
|
472
|
+
const variableValues = {
|
|
473
|
+
programAddress: 'AmtpVzo6H6qQCP9dH9wfu5hfa8kKaAFpTJ4aamPYR6V6',
|
|
474
|
+
};
|
|
475
|
+
|
|
476
|
+
const result = await rpcGraphQL.query(source, variableValues);
|
|
477
|
+
```
|
|
478
|
+
|
|
479
|
+
```
|
|
480
|
+
data: {
|
|
481
|
+
programAccounts: [
|
|
482
|
+
{
|
|
483
|
+
executable: false,
|
|
484
|
+
lamports: 10290815n,
|
|
485
|
+
rentEpoch: 0n,
|
|
486
|
+
},
|
|
487
|
+
{
|
|
488
|
+
executable: false,
|
|
489
|
+
lamports: 10290815n,
|
|
490
|
+
rentEpoch: 0n,
|
|
491
|
+
}
|
|
492
|
+
]
|
|
493
|
+
}
|
|
494
|
+
```
|
|
495
|
+
|
|
496
|
+
### Specific Program Account Types
|
|
497
|
+
|
|
498
|
+
Although specific parsed account types are directly tied to the program which
|
|
499
|
+
owns them, it's still possible to handle various specific account types within
|
|
500
|
+
the same program accounts response.
|
|
501
|
+
|
|
502
|
+
```typescript
|
|
503
|
+
const source = `
|
|
504
|
+
query myQuery($programAddress: String!) {
|
|
505
|
+
programAccounts(programAddress: $address) {
|
|
506
|
+
... on MintAccount {
|
|
507
|
+
data {
|
|
508
|
+
decimals
|
|
509
|
+
isInitialized
|
|
510
|
+
mintAuthority
|
|
511
|
+
supply
|
|
512
|
+
}
|
|
513
|
+
meta {
|
|
514
|
+
type
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
... on TokenAccount {
|
|
518
|
+
data {
|
|
519
|
+
isNative
|
|
520
|
+
mint
|
|
521
|
+
owner
|
|
522
|
+
state
|
|
523
|
+
}
|
|
524
|
+
meta {
|
|
525
|
+
type
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
`;
|
|
531
|
+
|
|
532
|
+
const variableValues = {
|
|
533
|
+
programAddress: 'AmtpVzo6H6qQCP9dH9wfu5hfa8kKaAFpTJ4aamPYR6V6',
|
|
534
|
+
};
|
|
535
|
+
|
|
536
|
+
const result = await rpcGraphQL.query(source, variableValues);
|
|
537
|
+
|
|
538
|
+
const { mints, tokenAccounts } = result.data.programAccounts.reduce(
|
|
539
|
+
(acc: { mints: any[]; tokenAccounts: any[] }, account) => {
|
|
540
|
+
const {
|
|
541
|
+
data: accountParsedInfo,
|
|
542
|
+
meta: {
|
|
543
|
+
type: accountType,
|
|
544
|
+
}
|
|
545
|
+
} = account;
|
|
546
|
+
if (accountType === "mint") {
|
|
547
|
+
acc.mints.push(accountParsedInfo);
|
|
548
|
+
} else {
|
|
549
|
+
acc.tokenAccounts.push(accountParsedInfo);
|
|
550
|
+
}
|
|
551
|
+
return acc;
|
|
552
|
+
},
|
|
553
|
+
{ mints: [], tokenAccounts: [] }
|
|
554
|
+
);
|
|
555
|
+
```
|
|
556
|
+
|
|
557
|
+
Account data encoding in `base58`, `base64`, and `base64+zstd` is also
|
|
558
|
+
supported, as well as `dataSlice` and `filter`!
|
|
559
|
+
|
|
560
|
+
```typescript
|
|
561
|
+
const source = `
|
|
562
|
+
query myQuery(
|
|
563
|
+
$programAddress: String!,
|
|
564
|
+
$commitment: Commitment,
|
|
565
|
+
$dataSlice: DataSlice,
|
|
566
|
+
$encoding: AccountEncoding,
|
|
567
|
+
) {
|
|
568
|
+
programAccounts(
|
|
569
|
+
programAddress: $programAddress,
|
|
570
|
+
commitment: $commitment,
|
|
571
|
+
dataSlice: $dataSlice,
|
|
572
|
+
encoding: $encoding,
|
|
573
|
+
) {
|
|
574
|
+
... on AccountBase64 {
|
|
575
|
+
data
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
`;
|
|
580
|
+
|
|
581
|
+
const variableValues = {
|
|
582
|
+
programAddress: 'DXngmJfjurhnAwbMPgpUGPH6qNvetCKRJ6PiD4ag4PTj',
|
|
583
|
+
commitment: 'confirmed',
|
|
584
|
+
dataSlice: {
|
|
585
|
+
length: 5,
|
|
586
|
+
offset: 0,
|
|
587
|
+
},
|
|
588
|
+
encoding: 'base64',
|
|
589
|
+
};
|
|
590
|
+
|
|
591
|
+
const result = await rpcGraphQL.query(source, variableValues);
|
|
592
|
+
```
|
|
593
|
+
|
|
594
|
+
```
|
|
595
|
+
data: {
|
|
596
|
+
programAccounts: [
|
|
597
|
+
{
|
|
598
|
+
data: 'dGVzdCA=',
|
|
599
|
+
},
|
|
600
|
+
],
|
|
601
|
+
}
|
|
602
|
+
```
|
|
603
|
+
|
|
604
|
+
### Nested Program Account Queries
|
|
605
|
+
|
|
606
|
+
Querying program accounts and applying nested queries to the objects within the
|
|
607
|
+
response list is an area where RPC-GraphQL really shines.
|
|
608
|
+
|
|
609
|
+
Consider an example where we want to get the **sum** of every lamports balance
|
|
610
|
+
of every **owner of the owner** of each token account, while discarding any
|
|
611
|
+
mint accounts.
|
|
612
|
+
|
|
613
|
+
```typescript
|
|
614
|
+
const source = `
|
|
615
|
+
query getLamportsOfOwnersOfOwnersOfTokenAccounts {
|
|
616
|
+
programAccounts(programAddress: "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA") {
|
|
617
|
+
... on TokenAccount {
|
|
618
|
+
data {
|
|
619
|
+
owner {
|
|
620
|
+
owner {
|
|
621
|
+
lamports
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
`;
|
|
629
|
+
|
|
630
|
+
const result = await rpcGraphQL.query(source);
|
|
631
|
+
|
|
632
|
+
const sumOfAllLamportsOfOwnersOfOwnersOfTokenAccounts = result.data
|
|
633
|
+
.map(o => o.account.data.owner.owner.lamports)
|
|
634
|
+
.reduce((acc, lamports) => acc + lamports, 0);
|
|
635
|
+
```
|
|
636
|
+
|
|
637
|
+
## Querying Transactions
|
|
638
|
+
|
|
639
|
+
The `Transaction` interface contains common fields across all transactions.
|
|
640
|
+
|
|
641
|
+
`src/schema/transaction/types.ts: TransactionInterface`
|
|
642
|
+
|
|
643
|
+
```graphql
|
|
644
|
+
interface Transaction {
|
|
645
|
+
blockTime: String
|
|
646
|
+
encoding: String
|
|
647
|
+
meta: TransactionMeta
|
|
648
|
+
slot: BigInt
|
|
649
|
+
}
|
|
650
|
+
```
|
|
651
|
+
|
|
652
|
+
Similar to account types, any transaction can be queried by these fields
|
|
653
|
+
without specifying the specific transaction type or the transaction meta
|
|
654
|
+
type.
|
|
655
|
+
|
|
656
|
+
```typescript
|
|
657
|
+
const source = `
|
|
658
|
+
query myQuery($signature: String!, $commitment: Commitment) {
|
|
659
|
+
transaction(signature: $signature, commitment: $commitment) {
|
|
660
|
+
blockTime
|
|
661
|
+
meta {
|
|
662
|
+
computeUnitsConsumed
|
|
663
|
+
logMessages
|
|
664
|
+
}
|
|
665
|
+
slot
|
|
666
|
+
}
|
|
667
|
+
}
|
|
668
|
+
`;
|
|
669
|
+
|
|
670
|
+
const variableValues = {
|
|
671
|
+
signature: '63zkpxATgAwXRGFQZPDESTw2m4uZQ99sX338ibgKtTcgG6v34E3MSS3zckCwJHrimS71cvei6h1Bn1K1De53BNWC',
|
|
672
|
+
commitment: 'confirmed',
|
|
673
|
+
};
|
|
674
|
+
|
|
675
|
+
const result = await rpcGraphQL.query(source, variableValues);
|
|
676
|
+
```
|
|
677
|
+
|
|
678
|
+
```
|
|
679
|
+
data: {
|
|
680
|
+
transaction: {
|
|
681
|
+
blockTime: 230860412n,
|
|
682
|
+
meta: {
|
|
683
|
+
computeUnitsConsumed: 120000n,
|
|
684
|
+
logMessages: [
|
|
685
|
+
"Program 8tfDNiaEyrV6Q1U4DEXrEigs9DoDtkugzFbybENEbCDz invoke [1]",
|
|
686
|
+
"Program 8tfDNiaEyrV6Q1U4DEXrEigs9DoDtkugzFbybENEbCDz consumed 2164 of 452155 compute units",
|
|
687
|
+
"Program 8tfDNiaEyrV6Q1U4DEXrEigs9DoDtkugzFbybENEbCDz success",
|
|
688
|
+
"Program ComputeBudget111111111111111111111111111111 invoke [1]",
|
|
689
|
+
"Program ComputeBudget111111111111111111111111111111 success"
|
|
690
|
+
]
|
|
691
|
+
},
|
|
692
|
+
slot: 230860693n,
|
|
693
|
+
},
|
|
694
|
+
}
|
|
695
|
+
```
|
|
696
|
+
|
|
697
|
+
### Specific Transaction Types
|
|
698
|
+
|
|
699
|
+
Each `jsonParsed` instruction type has its own GraphQL type that can be used in
|
|
700
|
+
a GraphQL transaction query.
|
|
701
|
+
|
|
702
|
+
Instructions for the following programs are supported.
|
|
703
|
+
|
|
704
|
+
- Address Lookup Table
|
|
705
|
+
- BPF Loader
|
|
706
|
+
- BPF Upgradeable Loader
|
|
707
|
+
- Stake
|
|
708
|
+
- SPL Associated Token
|
|
709
|
+
- SPL Memo
|
|
710
|
+
- SPL Token
|
|
711
|
+
- System
|
|
712
|
+
- Vote
|
|
713
|
+
|
|
714
|
+
Note at this time Token 2022 extensions are not yet supported.
|
|
715
|
+
|
|
716
|
+
Similar to accounts, transactions with encoded data are also supported.
|
|
717
|
+
|
|
718
|
+
- `TransactionBase58`: A Solana transaction with base58 encoded data
|
|
719
|
+
- `TransactionBase64`: A Solana transaction with base64 encoded data
|
|
720
|
+
- `TransactionJson`: A Solana transaction with JSON data
|
|
721
|
+
|
|
722
|
+
Specific instruction types can be used in the transaction's instructions. The
|
|
723
|
+
default instruction if it cannot be parsed using `jsonParsed` is the JSON
|
|
724
|
+
version dubbed `GenericInstruction`.
|
|
725
|
+
|
|
726
|
+
```typescript
|
|
727
|
+
const source = `
|
|
728
|
+
query myQuery($signature: String!, $commitment: Commitment) {
|
|
729
|
+
transaction(signature: $signature, commitment: $commitment) {
|
|
730
|
+
... on TransactionParsed {
|
|
731
|
+
data {
|
|
732
|
+
message {
|
|
733
|
+
accountKeys {
|
|
734
|
+
pubkey
|
|
735
|
+
signer
|
|
736
|
+
source
|
|
737
|
+
writable
|
|
738
|
+
}
|
|
739
|
+
instructions {
|
|
740
|
+
... on GenericInstruction {
|
|
741
|
+
accounts
|
|
742
|
+
data
|
|
743
|
+
programId
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
}
|
|
747
|
+
}
|
|
748
|
+
}
|
|
749
|
+
}
|
|
750
|
+
}
|
|
751
|
+
`;
|
|
752
|
+
|
|
753
|
+
const variableValues = {
|
|
754
|
+
signature: '63zkpxATgAwXRGFQZPDESTw2m4uZQ99sX338ibgKtTcgG6v34E3MSS3zckCwJHrimS71cvei6h1Bn1K1De53BNWC',
|
|
755
|
+
commitment: 'confirmed',
|
|
756
|
+
};
|
|
757
|
+
|
|
758
|
+
const result = await rpcGraphQL.query(source, variableValues);
|
|
759
|
+
```
|
|
19
760
|
|
|
20
|
-
|
|
21
|
-
|
|
761
|
+
```
|
|
762
|
+
data: {
|
|
763
|
+
transaction: {
|
|
764
|
+
data: {
|
|
765
|
+
message: {
|
|
766
|
+
accountKeys: [
|
|
767
|
+
{
|
|
768
|
+
pubkey: '81EBmTWaMkFqW6LPNPfU2478nJkrhCLuiFUPSdvQKQj7',
|
|
769
|
+
signer: false,
|
|
770
|
+
source: 'transaction',
|
|
771
|
+
writable: true,
|
|
772
|
+
},
|
|
773
|
+
{
|
|
774
|
+
pubkey: 'G6TmQyEoxbUzdyncwxVN9GgfALpYErHSkXZeqJj7fwFz',
|
|
775
|
+
signer: true,
|
|
776
|
+
source: 'transaction',
|
|
777
|
+
writable: true,
|
|
778
|
+
},
|
|
779
|
+
],
|
|
780
|
+
instructions: [
|
|
781
|
+
{
|
|
782
|
+
accounts: [
|
|
783
|
+
'81EBmTWaMkFqW6LPNPfU2478nJkrhCLuiFUPSdvQKQj7',
|
|
784
|
+
'G6TmQyEoxbUzdyncwxVN9GgfALpYErHSkXZeqJj7fwFz'
|
|
785
|
+
]
|
|
786
|
+
data: 'WzIsIDU0LCA5LCAgNzYsIDM1LCA2NCwgOCwgOCwgNCwgMywgMiwgNV0=',
|
|
787
|
+
programId: 'EksBYH1iSR8farQc9X26pYrXotj1D2JjXGuj8uM8xMcb',
|
|
788
|
+
}
|
|
789
|
+
]
|
|
790
|
+
},
|
|
791
|
+
},
|
|
792
|
+
},
|
|
793
|
+
}
|
|
794
|
+
```
|
|
22
795
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
applications revolves around two components:
|
|
796
|
+
However, whenever JSON-parseable instructions are present in the list of
|
|
797
|
+
instructions, they can be queried using specific instruction types.
|
|
26
798
|
|
|
27
|
-
|
|
28
|
-
|
|
799
|
+
```typescript
|
|
800
|
+
const source = `
|
|
801
|
+
query myQuery($signature: String!, $commitment: Commitment) {
|
|
802
|
+
transaction(signature: $signature, commitment: $commitment) {
|
|
803
|
+
... on TransactionParsed {
|
|
804
|
+
data {
|
|
805
|
+
message {
|
|
806
|
+
instructions {
|
|
807
|
+
... on CreateAccountInstruction {
|
|
808
|
+
data {
|
|
809
|
+
lamports
|
|
810
|
+
space
|
|
811
|
+
}
|
|
812
|
+
meta {
|
|
813
|
+
program
|
|
814
|
+
}
|
|
815
|
+
}
|
|
816
|
+
}
|
|
817
|
+
}
|
|
818
|
+
}
|
|
819
|
+
}
|
|
820
|
+
}
|
|
821
|
+
}
|
|
822
|
+
`;
|
|
29
823
|
|
|
30
|
-
|
|
824
|
+
const variableValues = {
|
|
825
|
+
signature: '63zkpxATgAwXRGFQZPDESTw2m4uZQ99sX338ibgKtTcgG6v34E3MSS3zckCwJHrimS71cvei6h1Bn1K1De53BNWC',
|
|
826
|
+
commitment: 'confirmed',
|
|
827
|
+
};
|
|
828
|
+
|
|
829
|
+
const result = await rpcGraphQL.query(source, variableValues);
|
|
830
|
+
```
|
|
31
831
|
|
|
32
|
-
|
|
832
|
+
```
|
|
833
|
+
data: {
|
|
834
|
+
transaction: {
|
|
835
|
+
data: {
|
|
836
|
+
message: {
|
|
837
|
+
instructions: [
|
|
838
|
+
{
|
|
839
|
+
data: {
|
|
840
|
+
lamports: 890880n,
|
|
841
|
+
space: 0n,
|
|
842
|
+
},
|
|
843
|
+
meta: {
|
|
844
|
+
program: 'system',
|
|
845
|
+
},
|
|
846
|
+
}
|
|
847
|
+
]
|
|
848
|
+
},
|
|
849
|
+
},
|
|
850
|
+
},
|
|
851
|
+
}
|
|
852
|
+
```
|
|
33
853
|
|
|
34
|
-
|
|
35
|
-
|
|
854
|
+
Querying transactions by their encoded data (`base58`, `base64`, `json`) is
|
|
855
|
+
still fully supported.
|
|
36
856
|
|
|
37
|
-
|
|
857
|
+
```typescript
|
|
858
|
+
const source = `
|
|
859
|
+
query myQuery(
|
|
860
|
+
$signature: String!,
|
|
861
|
+
$commitment: Commitment,
|
|
862
|
+
$encoding: TransactionEncoding!,
|
|
863
|
+
) {
|
|
864
|
+
transaction(
|
|
865
|
+
signature: $signature,
|
|
866
|
+
commitment: $commitment,
|
|
867
|
+
encoding: $encoding,
|
|
868
|
+
) {
|
|
869
|
+
... on TransactionBase64 {
|
|
870
|
+
data
|
|
871
|
+
}
|
|
872
|
+
}
|
|
873
|
+
}
|
|
874
|
+
`;
|
|
38
875
|
|
|
39
|
-
|
|
876
|
+
const variableValues = {
|
|
877
|
+
signature: '63zkpxATgAwXRGFQZPDESTw2m4uZQ99sX338ibgKtTcgG6v34E3MSS3zckCwJHrimS71cvei6h1Bn1K1De53BNWC',
|
|
878
|
+
commitment: 'confirmed',
|
|
879
|
+
encoding: 'base64',
|
|
880
|
+
};
|
|
881
|
+
|
|
882
|
+
const result = await rpcGraphQL.query(source, variableValues);
|
|
883
|
+
```
|
|
40
884
|
|
|
41
|
-
|
|
885
|
+
```
|
|
886
|
+
data: {
|
|
887
|
+
transaction: {
|
|
888
|
+
data: 'WzIsIDU0LCA5LCAgNzYsIDM1LCA2NCwgOCwgOCwgNCwgMywgMiwgNV0=',
|
|
889
|
+
},
|
|
890
|
+
}
|
|
891
|
+
```
|
|
42
892
|
|
|
43
|
-
|
|
893
|
+
### Nested Transaction Queries
|
|
44
894
|
|
|
45
|
-
|
|
895
|
+
Since transactions have a relatively large number of data points, they are
|
|
896
|
+
particularly useful for nested queries!
|
|
46
897
|
|
|
47
|
-
|
|
898
|
+
Similar to nested querying accounts, it's possible to nest queries inside your
|
|
899
|
+
transaction queries to look up other objects, such as accounts, as they appear
|
|
900
|
+
in the transaction response.
|
|
48
901
|
|
|
49
|
-
|
|
902
|
+
```typescript
|
|
903
|
+
const source = `
|
|
904
|
+
query myQuery($signature: String!, $commitment: Commitment) {
|
|
905
|
+
transaction(signature: $signature, commitment: $commitment) {
|
|
906
|
+
... on TransactionParsed {
|
|
907
|
+
data {
|
|
908
|
+
message {
|
|
909
|
+
instructions {
|
|
910
|
+
... on SplTokenTransferInstruction {
|
|
911
|
+
data {
|
|
912
|
+
amount
|
|
913
|
+
authority {
|
|
914
|
+
address
|
|
915
|
+
lamports
|
|
916
|
+
}
|
|
917
|
+
destination {
|
|
918
|
+
... on TokenAccount {
|
|
919
|
+
data {
|
|
920
|
+
address
|
|
921
|
+
mint {
|
|
922
|
+
... on MintAccount {
|
|
923
|
+
data {
|
|
924
|
+
address
|
|
925
|
+
decimals
|
|
926
|
+
}
|
|
927
|
+
}
|
|
928
|
+
}
|
|
929
|
+
owner {
|
|
930
|
+
address
|
|
931
|
+
lamports
|
|
932
|
+
}
|
|
933
|
+
}
|
|
934
|
+
}
|
|
935
|
+
}
|
|
936
|
+
source {
|
|
937
|
+
... on TokenAccount {
|
|
938
|
+
data {
|
|
939
|
+
address
|
|
940
|
+
mint {
|
|
941
|
+
... on MintAccount {
|
|
942
|
+
data {
|
|
943
|
+
address
|
|
944
|
+
decimals
|
|
945
|
+
}
|
|
946
|
+
}
|
|
947
|
+
}
|
|
948
|
+
owner {
|
|
949
|
+
address
|
|
950
|
+
lamports
|
|
951
|
+
}
|
|
952
|
+
}
|
|
953
|
+
}
|
|
954
|
+
}
|
|
955
|
+
}
|
|
956
|
+
meta {
|
|
957
|
+
program
|
|
958
|
+
}
|
|
959
|
+
}
|
|
960
|
+
}
|
|
961
|
+
}
|
|
962
|
+
}
|
|
963
|
+
}
|
|
964
|
+
}
|
|
965
|
+
}
|
|
966
|
+
`;
|
|
50
967
|
|
|
51
|
-
|
|
968
|
+
const variableValues = {
|
|
969
|
+
signature: '63zkpxATgAwXRGFQZPDESTw2m4uZQ99sX338ibgKtTcgG6v34E3MSS3zckCwJHrimS71cvei6h1Bn1K1De53BNWC',
|
|
970
|
+
commitment: 'confirmed',
|
|
971
|
+
};
|
|
972
|
+
|
|
973
|
+
const result = await rpcGraphQL.query(source, variableValues);
|
|
974
|
+
```
|
|
52
975
|
|
|
53
|
-
|
|
976
|
+
```
|
|
977
|
+
data: {
|
|
978
|
+
transaction: {
|
|
979
|
+
data: {
|
|
980
|
+
message: {
|
|
981
|
+
instructions: [
|
|
982
|
+
{
|
|
983
|
+
data: {
|
|
984
|
+
amount: '50',
|
|
985
|
+
authority: {
|
|
986
|
+
address: 'AHPPMhzDQix9sKULBqeaQ5BUZgrKdz8tg6DzPxsofB12',
|
|
987
|
+
lamports: 890880n,
|
|
988
|
+
},
|
|
989
|
+
destination: {
|
|
990
|
+
data: {
|
|
991
|
+
address: '2W8mUY75zxqwAcpirn75r3Cc7TStMirFyHwKqo13fmB1',
|
|
992
|
+
mint: data: {
|
|
993
|
+
address: '8poKMotB2cEYVv5sbjrdyssASZj1vwYCe7GJFeXo2QP7',
|
|
994
|
+
decimals: 6,
|
|
995
|
+
},
|
|
996
|
+
owner: {
|
|
997
|
+
address: '7tRxJ2znbTFpwW9XaMMiDsXDudoPEUXRcpDpm8qjWgAZ',
|
|
998
|
+
lamports: 890880n,
|
|
999
|
+
},
|
|
1000
|
+
}
|
|
1001
|
+
},
|
|
1002
|
+
source: {
|
|
1003
|
+
data: {
|
|
1004
|
+
parsed: {
|
|
1005
|
+
info: {
|
|
1006
|
+
address: 'BqFCPqXUm4cq6jaZZx1TDTvUR1wdEuNNwAHBEVR6mJhM',
|
|
1007
|
+
mint: data: {
|
|
1008
|
+
address: '8poKMotB2cEYVv5sbjrdyssASZj1vwYCe7GJFeXo2QP7',
|
|
1009
|
+
decimals: 6,
|
|
1010
|
+
},
|
|
1011
|
+
owner: {
|
|
1012
|
+
address: '3dPmVLMD7PC5faZNyJUH9WFrUxAsbjydJfoozwmR1wDG',
|
|
1013
|
+
lamports: e890880n,
|
|
1014
|
+
},
|
|
1015
|
+
}
|
|
1016
|
+
}
|
|
1017
|
+
}
|
|
1018
|
+
},
|
|
1019
|
+
},
|
|
1020
|
+
meta: {
|
|
1021
|
+
program: 'spl-token',
|
|
1022
|
+
}
|
|
1023
|
+
}
|
|
1024
|
+
]
|
|
1025
|
+
},
|
|
1026
|
+
},
|
|
1027
|
+
},
|
|
1028
|
+
}
|
|
1029
|
+
```
|
|
54
1030
|
|
|
55
|
-
|
|
1031
|
+
## Querying Blocks
|
|
56
1032
|
|
|
57
|
-
|
|
1033
|
+
Querying blocks is very similar to querying transactions, since a block
|
|
1034
|
+
contains a list of transactions. There's a bit more data at the highest level
|
|
1035
|
+
for a block, but you can query the list of transactions using a block query and
|
|
1036
|
+
transaction types in the same fashion you can query the lsit of accounts using
|
|
1037
|
+
a program accounts query and account types.
|
|
58
1038
|
|
|
59
|
-
|
|
1039
|
+
```typescript
|
|
1040
|
+
const source = `
|
|
1041
|
+
query myQuery($slot: BigInt!, $commitment: Commitment) {
|
|
1042
|
+
block(slot: $slot, commitment: $commitment) {
|
|
1043
|
+
blockHeight
|
|
1044
|
+
blockhash
|
|
1045
|
+
parentSlot
|
|
1046
|
+
rewards {
|
|
1047
|
+
commission
|
|
1048
|
+
lamports
|
|
1049
|
+
rewardType
|
|
1050
|
+
}
|
|
1051
|
+
transactions {
|
|
1052
|
+
... on TransactionParsed {
|
|
1053
|
+
data {
|
|
1054
|
+
message {
|
|
1055
|
+
instructions {
|
|
1056
|
+
... on CreateAccountInstruction {
|
|
1057
|
+
data {
|
|
1058
|
+
lamports
|
|
1059
|
+
space
|
|
1060
|
+
}
|
|
1061
|
+
meta {
|
|
1062
|
+
program
|
|
1063
|
+
}
|
|
1064
|
+
}
|
|
1065
|
+
}
|
|
1066
|
+
}
|
|
1067
|
+
}
|
|
1068
|
+
}
|
|
1069
|
+
}
|
|
1070
|
+
}
|
|
1071
|
+
}
|
|
1072
|
+
`;
|
|
60
1073
|
|
|
61
|
-
|
|
1074
|
+
const variableValues = {
|
|
1075
|
+
slot: 43596n,
|
|
1076
|
+
commitment: 'confirmed',
|
|
1077
|
+
};
|
|
1078
|
+
|
|
1079
|
+
const result = await rpcGraphQL.query(source, variableValues);
|
|
1080
|
+
```
|
|
62
1081
|
|
|
63
|
-
|
|
1082
|
+
```
|
|
1083
|
+
data: {
|
|
1084
|
+
block: {
|
|
1085
|
+
blockHeight: 196758578n,
|
|
1086
|
+
blockhash: 'BqFCPqXUm4cq6jaZZx1TDTvUR1wdEuNNwAHBEVR6mJhM',
|
|
1087
|
+
parentSlot: 230862408n,
|
|
1088
|
+
rewards: [
|
|
1089
|
+
{
|
|
1090
|
+
commission: 0.05,
|
|
1091
|
+
lamports: 58578n,
|
|
1092
|
+
rewardType: 'staking',
|
|
1093
|
+
},
|
|
1094
|
+
{
|
|
1095
|
+
commission: 0.05,
|
|
1096
|
+
lamports: 58578n,
|
|
1097
|
+
rewardType: 'staking',
|
|
1098
|
+
}
|
|
1099
|
+
],
|
|
1100
|
+
transactions: [
|
|
1101
|
+
data: {
|
|
1102
|
+
{
|
|
1103
|
+
message: {
|
|
1104
|
+
instructions: [
|
|
1105
|
+
{
|
|
1106
|
+
data: {
|
|
1107
|
+
lamports: 890880n,
|
|
1108
|
+
space: 0n,
|
|
1109
|
+
},
|
|
1110
|
+
meta: {
|
|
1111
|
+
program: 'system',
|
|
1112
|
+
},
|
|
1113
|
+
}
|
|
1114
|
+
]
|
|
1115
|
+
},
|
|
1116
|
+
}
|
|
1117
|
+
}
|
|
1118
|
+
],
|
|
1119
|
+
},
|
|
1120
|
+
}
|
|
1121
|
+
```
|