@ixo/oracle-runtime-workers 0.29.1 → 0.31.0

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.
Files changed (74) hide show
  1. package/package.json +7 -5
  2. package/src/attachments/channel-links.ts +135 -0
  3. package/src/attachments/channel.ts +203 -0
  4. package/src/attachments/download.ts +23 -6
  5. package/src/attachments/index.ts +23 -0
  6. package/src/attachments/pipeline.ts +120 -42
  7. package/src/attachments/retention.ts +11 -3
  8. package/src/attachments/sanitize.ts +20 -8
  9. package/src/attachments/types.ts +7 -0
  10. package/src/attachments/view.ts +24 -7
  11. package/src/channels/contract.ts +69 -0
  12. package/src/channels/turns.ts +23 -1
  13. package/src/core/main-agent-types.ts +2 -0
  14. package/src/core/runtime-context.ts +3 -0
  15. package/src/delivery/plan.ts +3 -1
  16. package/src/do/contracts.ts +3 -0
  17. package/src/do/turn-attachments.ts +103 -0
  18. package/src/do/user-oracle-do.ts +142 -42
  19. package/src/hub-actions/client.ts +87 -7
  20. package/src/hub-actions/hub-text.ts +82 -0
  21. package/src/hub-actions/request.ts +7 -4
  22. package/src/hub-actions/store.ts +5 -1
  23. package/src/hub-actions/transfer.ts +23 -6
  24. package/src/index.ts +1 -0
  25. package/src/plugin-api/index.ts +1 -0
  26. package/src/plugin-api/types.ts +43 -2
  27. package/src/plugins/attachments/view-attachment-tool.ts +7 -3
  28. package/src/plugins/hub-actions/hub-actions.plugin.ts +96 -17
  29. package/src/plugins/ixo-chain/balances.ts +141 -0
  30. package/src/plugins/ixo-chain/blocksync.ts +17 -8
  31. package/src/plugins/ixo-chain/denoms.ts +84 -36
  32. package/src/plugins/ixo-chain/http.ts +315 -70
  33. package/src/plugins/ixo-chain/ixo-chain.plugin.ts +182 -301
  34. package/src/plugins/ixo-chain/kinds/chain/account.ts +516 -0
  35. package/src/plugins/ixo-chain/kinds/chain/claims.ts +287 -0
  36. package/src/plugins/ixo-chain/kinds/chain/economics.ts +237 -0
  37. package/src/plugins/ixo-chain/kinds/chain/governance.ts +455 -0
  38. package/src/plugins/ixo-chain/kinds/chain/grants.ts +682 -0
  39. package/src/plugins/ixo-chain/kinds/chain/index.ts +23 -0
  40. package/src/plugins/ixo-chain/kinds/chain/liquid-staking.ts +279 -0
  41. package/src/plugins/ixo-chain/kinds/chain/shared.ts +286 -0
  42. package/src/plugins/ixo-chain/kinds/chain/staking.ts +220 -0
  43. package/src/plugins/ixo-chain/kinds/coins.ts +112 -0
  44. package/src/plugins/ixo-chain/kinds/core.ts +246 -0
  45. package/src/plugins/ixo-chain/kinds/indexed/agent-deposits.ts +124 -0
  46. package/src/plugins/ixo-chain/kinds/indexed/dao-proposals.ts +379 -0
  47. package/src/plugins/ixo-chain/kinds/indexed/daos.ts +319 -0
  48. package/src/plugins/ixo-chain/kinds/indexed/disputes.ts +159 -0
  49. package/src/plugins/ixo-chain/kinds/indexed/evaluations.ts +172 -0
  50. package/src/plugins/ixo-chain/kinds/indexed/index.ts +21 -0
  51. package/src/plugins/ixo-chain/kinds/indexed/liquid-stake-history.ts +160 -0
  52. package/src/plugins/ixo-chain/kinds/indexed/member-budgets.ts +175 -0
  53. package/src/plugins/ixo-chain/kinds/indexed/shared.ts +211 -0
  54. package/src/plugins/ixo-chain/kinds/indexed/token-history.ts +205 -0
  55. package/src/plugins/ixo-chain/kinds/registry.ts +43 -0
  56. package/src/plugins/ixo-chain/kinds/types.ts +156 -0
  57. package/src/plugins/ixo-chain/lookup.ts +470 -0
  58. package/src/plugins/ixo-chain/overview.ts +1060 -0
  59. package/src/plugins/ixo-chain/queries.ts +170 -138
  60. package/src/plugins/ixo-chain/rest.ts +135 -54
  61. package/src/plugins/ixo-chain/summaries.ts +3 -2
  62. package/src/plugins/yoma/catalog.ts +780 -0
  63. package/src/plugins/yoma/clef.ts +98 -0
  64. package/src/plugins/yoma/drafts.ts +339 -0
  65. package/src/plugins/yoma/engine.ts +926 -0
  66. package/src/plugins/yoma/index.ts +13 -0
  67. package/src/plugins/yoma/judge.ts +358 -0
  68. package/src/plugins/yoma/permission.ts +62 -0
  69. package/src/plugins/yoma/reads.ts +195 -0
  70. package/src/plugins/yoma/submission.ts +534 -0
  71. package/src/plugins/yoma/text.ts +16 -0
  72. package/src/plugins/yoma/work.ts +190 -0
  73. package/src/plugins/yoma/yoma.plugin.ts +2162 -0
  74. package/src/sqlite/serialization.ts +2 -0
@@ -0,0 +1,220 @@
1
+ /**
2
+ * `staking`: an account's delegations, unbonding entries and pending
3
+ * rewards, with each validator's moniker. Three reads at once; monikers
4
+ * come from a per-isolate cache. A failed rewards read leaves the
5
+ * delegations standing, marked `rewardsUnavailable`.
6
+ */
7
+ import { z } from 'zod';
8
+ import { defineKind, type KindContext, type KindResult } from '../types';
9
+ import { displayCoin, ixo, wholeUnits } from '../coins';
10
+ import { clip } from '../../summaries';
11
+ import {
12
+ ReadCache,
13
+ accountFor,
14
+ addressArg,
15
+ coinSchema,
16
+ coinsOr,
17
+ coinsSchema,
18
+ failed,
19
+ } from './shared';
20
+
21
+ /** A validator operator address. */
22
+ const VALOPER = /^ixovaloper1[0-9a-z]{38,58}$/;
23
+ /** Delegations and unbonding validators read per account (one page each). */
24
+ const STAKING_PAGE = 50;
25
+ /** Validators whose moniker is looked up per request; the others are shown by address. */
26
+ const MONIKER_LOOKUPS = 20;
27
+ /** A moniker (or a validator's absence) is reused for 10 min. */
28
+ export const MONIKER_TTL_MS = 600_000;
29
+ const MONIKER_CACHE_LIMIT = 256;
30
+
31
+ const monikers = new ReadCache<string | null>(
32
+ MONIKER_TTL_MS,
33
+ MONIKER_CACHE_LIMIT,
34
+ );
35
+
36
+ const validatorResponse = z.object({
37
+ validator: z.object({ description: z.object({ moniker: z.string() }) }),
38
+ });
39
+
40
+ /** A validator's moniker; null when it has none or the chain has no such validator. */
41
+ function monikerOf(ctx: KindContext, valoper: string) {
42
+ return monikers.get(ctx, valoper, async () => {
43
+ const read = await ctx.rest(
44
+ `/cosmos/staking/v1beta1/validators/${valoper}`,
45
+ validatorResponse,
46
+ { label: 'validator', notFoundOn404: true, maxBytes: 64 * 1024 },
47
+ );
48
+ if (read.ok)
49
+ return {
50
+ ok: true,
51
+ value: clip(read.value.validator.description.moniker, 60) || null,
52
+ };
53
+ return read.failure.reason === 'not_found'
54
+ ? { ok: true, value: null }
55
+ : read;
56
+ });
57
+ }
58
+
59
+ const pagination = z.object({ next_key: z.string().nullish() }).nullish();
60
+ const delegationsResponse = z.object({
61
+ delegation_responses: z.array(
62
+ z.object({
63
+ delegation: z.object({ validator_address: z.string() }),
64
+ balance: coinSchema,
65
+ }),
66
+ ),
67
+ pagination,
68
+ });
69
+ const unbondingResponse = z.object({
70
+ unbonding_responses: z.array(
71
+ z.object({
72
+ validator_address: z.string(),
73
+ entries: z.array(
74
+ z.object({ completion_time: z.string(), balance: z.string() }),
75
+ ),
76
+ }),
77
+ ),
78
+ pagination,
79
+ });
80
+ const rewardsResponse = z.object({
81
+ rewards: z
82
+ .array(z.object({ validator_address: z.string(), reward: coinsSchema }))
83
+ .default([]),
84
+ total: coinsSchema.default([]),
85
+ });
86
+
87
+ /** The sum of whole base units. */
88
+ const sum = (amounts: readonly string[]) =>
89
+ amounts.reduce((total, units) => total + BigInt(units), 0n).toString();
90
+
91
+ const args = z.strictObject({ address: addressArg });
92
+
93
+ export const stakingKind = defineKind({
94
+ name: 'staking',
95
+ summary:
96
+ "An account's staked IXO: delegations, unbonding, rewards waiting to be claimed.",
97
+ explain: [
98
+ 'Staking = delegating IXO to validators, who secure the chain; delegated IXO earns rewards and is not in the bank balance. `delegations`: per validator (`moniker`, `validator` address) the IXO delegated now (`coin`). `unbonding`: IXO being undelegated (`coin`), returned to the bank balance at `completesAt` (it earns nothing meanwhile). `rewards`: earned and not yet withdrawn (claiming them is a transaction), in total and per validator (`coins`). `totals` adds them up. `rewardsUnavailable: true` = the rewards could not be read; the delegations still stand.',
99
+ 'Liquid staking is staking too: IXO staked into a liquid staking pool (e.g. for PAY) is delegated by the pool, not by the account, so it is not listed here: see `liquid_staking`.',
100
+ '`staking: false` = no delegations and nothing unbonding (rewards may still be waiting). Amounts are display units (`amount` + `symbol`) with `amountBaseUnits`; reward fractions of a base unit are dropped. `moreDelegations` / `moreUnbonding` = more than 50 validators, the rest not read.',
101
+ ].join('\n'),
102
+ source: 'chain',
103
+ list: false,
104
+ args,
105
+ example: {},
106
+ plan(input, ctx) {
107
+ const account = accountFor(ctx, input.address);
108
+ if ('invalid' in account) return account;
109
+ return {
110
+ source: 'chain',
111
+ async run(): Promise<KindResult> {
112
+ const page = `pagination.limit=${STAKING_PAGE}`;
113
+ const [delegations, unbonding, rewards] = await Promise.all([
114
+ ctx.rest(
115
+ `/cosmos/staking/v1beta1/delegations/${account.address}?${page}`,
116
+ delegationsResponse,
117
+ { label: 'delegations' },
118
+ ),
119
+ ctx.rest(
120
+ `/cosmos/staking/v1beta1/delegators/${account.address}/unbonding_delegations?${page}`,
121
+ unbondingResponse,
122
+ { label: 'unbonding delegations' },
123
+ ),
124
+ ctx.rest(
125
+ `/cosmos/distribution/v1beta1/delegators/${account.address}/rewards`,
126
+ rewardsResponse,
127
+ { label: 'staking rewards' },
128
+ ),
129
+ ]);
130
+ if (!delegations.ok) return failed(delegations.failure);
131
+ if (!unbonding.ok) return failed(unbonding.failure);
132
+ const earned = rewards.ok ? rewards.value : null;
133
+ const validators = [
134
+ ...new Set([
135
+ ...delegations.value.delegation_responses.map(
136
+ (row) => row.delegation.validator_address,
137
+ ),
138
+ ...unbonding.value.unbonding_responses.map(
139
+ (row) => row.validator_address,
140
+ ),
141
+ ...(earned?.rewards ?? []).map((row) => row.validator_address),
142
+ ]),
143
+ ].filter((valoper) => VALOPER.test(valoper));
144
+ const names = new Map<string, string>();
145
+ await Promise.all(
146
+ validators.slice(0, MONIKER_LOOKUPS).map(async (valoper) => {
147
+ const moniker = await monikerOf(ctx, valoper);
148
+ if (moniker.ok && moniker.value) names.set(valoper, moniker.value);
149
+ }),
150
+ );
151
+ const who = (valoper: string) => {
152
+ const moniker = names.get(valoper);
153
+ return {
154
+ validator: clip(valoper, 80),
155
+ ...(moniker ? { moniker } : {}),
156
+ };
157
+ };
158
+ const delegated = await Promise.all(
159
+ delegations.value.delegation_responses.map(async (row) => ({
160
+ ...who(row.delegation.validator_address),
161
+ coin: await displayCoin(ctx, row.balance),
162
+ })),
163
+ );
164
+ // Unbonding balances are in the bond denom, uixo on every IXO network.
165
+ const entries = unbonding.value.unbonding_responses.flatMap((row) =>
166
+ row.entries.flatMap((entry) => {
167
+ const units = wholeUnits(entry.balance);
168
+ return units === null
169
+ ? []
170
+ : [
171
+ {
172
+ ...who(row.validator_address),
173
+ coin: ixo(units),
174
+ completesAt: entry.completion_time,
175
+ },
176
+ ];
177
+ }),
178
+ );
179
+ const bonded = delegated.flatMap((row) =>
180
+ row.coin?.denom === 'uixo' ? [row.coin.amountBaseUnits] : [],
181
+ );
182
+ return {
183
+ ok: true,
184
+ subject: account.subject,
185
+ data: {
186
+ address: account.address,
187
+ staking: delegated.length > 0 || entries.length > 0,
188
+ delegations: delegated,
189
+ unbonding: entries,
190
+ ...(earned
191
+ ? {
192
+ rewards: {
193
+ total: await coinsOr(ctx, earned.total, 'none'),
194
+ byValidator: await Promise.all(
195
+ earned.rewards.map(async (row) => ({
196
+ ...who(row.validator_address),
197
+ coins: await coinsOr(ctx, row.reward, 'none'),
198
+ })),
199
+ ),
200
+ },
201
+ }
202
+ : { rewardsUnavailable: true }),
203
+ totals: {
204
+ delegated: ixo(sum(bonded)),
205
+ unbonding: ixo(
206
+ sum(entries.map((row) => row.coin.amountBaseUnits)),
207
+ ),
208
+ },
209
+ ...(delegations.value.pagination?.next_key
210
+ ? { moreDelegations: true }
211
+ : {}),
212
+ ...(unbonding.value.pagination?.next_key
213
+ ? { moreUnbonding: true }
214
+ : {}),
215
+ },
216
+ };
217
+ },
218
+ };
219
+ },
220
+ });
@@ -0,0 +1,112 @@
1
+ /**
2
+ * Bank coins as every kind shows them: `{ denom, symbol, amount,
3
+ * amountBaseUnits, verified, origin?, trace?, metadataUnavailable? }`, the
4
+ * `amount` converted to display units through the call's denom displays
5
+ * (`KindContext.display`). IXO 1155 tokens are not bank coins: their
6
+ * amounts stay whole units.
7
+ */
8
+ import { formatUnits, type IbcTrace, type TokenDisplay } from '../denoms';
9
+ import type { KindContext } from './types';
10
+
11
+ /** A bank coin as shown: display amount and symbol, with the base units it came from. */
12
+ export type DisplayCoin = {
13
+ denom: string;
14
+ symbol: string;
15
+ /** Display units (`amountBaseUnits` ÷ 10^decimals); base units when unverified. */
16
+ amount: string;
17
+ amountBaseUnits: string;
18
+ verified: boolean;
19
+ /** The chain a verified IBC token came from: tells apart two tokens of one symbol. */
20
+ origin?: string;
21
+ /** What an unverified IBC token's trace claims: self-reported, never what the token is. */
22
+ trace?: IbcTrace;
23
+ /** Its metadata was not read: it may still be verified. */
24
+ metadataUnavailable?: true;
25
+ };
26
+
27
+ /** A chain coin: a denom and an amount as the chain's JSON gives it. */
28
+ export type ChainCoin = { denom: string; amount: string };
29
+
30
+ /** Coins shown per list; the rest are left out. */
31
+ export const COIN_CAP = 10;
32
+
33
+ /** The rule every kind's `explain` states for its bank coins. */
34
+ export const COINS_NOTE =
35
+ 'Bank coins: `amount` in display units beside `symbol` (uixo → IXO, upay → PAY, both 6 decimals), with `amountBaseUnits`; an unverified token (`verified: false`) is in base units under its full denom.';
36
+
37
+ /**
38
+ * Whole base units of a Coin or DecCoin amount (a DecCoin's fraction, a
39
+ * share of one base unit, is dropped); null when it is not a non-negative
40
+ * decimal of at most 40 digits.
41
+ */
42
+ export function wholeUnits(amount: string): string | null {
43
+ return /^(0|[1-9][0-9]{0,39})(?:\.[0-9]{1,18})?$/.exec(amount)?.[1] ?? null;
44
+ }
45
+
46
+ /** `baseUnits` of `denom` as shown with `display`. */
47
+ export function coinView(
48
+ denom: string,
49
+ baseUnits: string,
50
+ display: TokenDisplay,
51
+ ): DisplayCoin {
52
+ return {
53
+ denom,
54
+ symbol: display.symbol,
55
+ amount: formatUnits(baseUnits, display.decimals),
56
+ amountBaseUnits: baseUnits,
57
+ verified: display.verified,
58
+ ...(display.origin !== undefined ? { origin: display.origin } : {}),
59
+ ...(display.trace !== undefined ? { trace: display.trace } : {}),
60
+ ...(display.metadataUnavailable ? { metadataUnavailable: true } : {}),
61
+ };
62
+ }
63
+
64
+ /** Each denom's display, looked up at once (the call's REST limit bounds them). */
65
+ export async function displaysOf(
66
+ ctx: Pick<KindContext, 'display'>,
67
+ denoms: readonly string[],
68
+ ): Promise<Map<string, TokenDisplay>> {
69
+ const out = new Map<string, TokenDisplay>();
70
+ await Promise.all(
71
+ [...new Set(denoms)].map(async (denom) => {
72
+ out.set(denom, await ctx.display(denom));
73
+ }),
74
+ );
75
+ return out;
76
+ }
77
+
78
+ /** Coins as shown, at most `max`; an amount that is not a decimal is left out. */
79
+ export async function displayCoins(
80
+ ctx: Pick<KindContext, 'display'>,
81
+ coins: readonly ChainCoin[],
82
+ max = COIN_CAP,
83
+ ): Promise<DisplayCoin[]> {
84
+ const shown = coins
85
+ .flatMap((coin) => {
86
+ const units = wholeUnits(coin.amount);
87
+ return units === null ? [] : [{ denom: coin.denom, units }];
88
+ })
89
+ .slice(0, max);
90
+ return Promise.all(
91
+ shown.map(async ({ denom, units }) =>
92
+ coinView(denom, units, await ctx.display(denom)),
93
+ ),
94
+ );
95
+ }
96
+
97
+ /** One coin as shown; null when its amount is not a decimal. */
98
+ export async function displayCoin(
99
+ ctx: Pick<KindContext, 'display'>,
100
+ coin: ChainCoin,
101
+ ): Promise<DisplayCoin | null> {
102
+ return (await displayCoins(ctx, [coin], 1))[0] ?? null;
103
+ }
104
+
105
+ /** IXO as shown, from base units (uixo). */
106
+ export function ixo(baseUnits: string): DisplayCoin {
107
+ return coinView('uixo', baseUnits, {
108
+ symbol: 'IXO',
109
+ decimals: 6,
110
+ verified: true,
111
+ });
112
+ }
@@ -0,0 +1,246 @@
1
+ /**
2
+ * The core kinds: claims, collections, entities, DID documents, 1155
3
+ * tokens and transactions, each one aliased root field of the call's
4
+ * Blocksync document. Their arguments, patterns and fields are in
5
+ * `queries.ts`; their answers are shaped by `summaries.ts`.
6
+ */
7
+ import type { UserIdentity } from '../../../core/user-identity';
8
+ import {
9
+ CORE_ARGS,
10
+ requestField,
11
+ type ChainRequest,
12
+ type Subject,
13
+ } from '../queries';
14
+ import { shapeResult } from '../summaries';
15
+ import {
16
+ defineKind,
17
+ type KindContext,
18
+ type KindDef,
19
+ type KindInvalid,
20
+ type KindPlan,
21
+ } from './types';
22
+
23
+ /** Whose a by-id record is, from the accounts the answer names as its owners. */
24
+ function ownerOf(
25
+ ownedBy: string[] | undefined,
26
+ identity: UserIdentity,
27
+ ): Subject | undefined {
28
+ if (!ownedBy) return undefined;
29
+ return identity.address && ownedBy.includes(identity.address)
30
+ ? 'user'
31
+ : 'other';
32
+ }
33
+
34
+ /** A core request as its aliased field and the shaping of that alias's answer. */
35
+ function blocksyncPlan(
36
+ request: ChainRequest,
37
+ ctx: KindContext,
38
+ ): KindPlan | KindInvalid {
39
+ const plan = requestField(request, ctx.identity, ctx.first);
40
+ if (!plan.ok) return { invalid: plan.detail };
41
+ return {
42
+ source: 'blocksync',
43
+ field: (alias) => `${alias}: ${plan.field}`,
44
+ shape(raw) {
45
+ const shaped = shapeResult(request, raw);
46
+ if (!shaped.ok) return { ok: false, ...shaped.failure };
47
+ const subject = plan.subject ?? ownerOf(shaped.ownedBy, ctx.identity);
48
+ return {
49
+ ok: true,
50
+ data: shaped.data,
51
+ ...(subject ? { subject } : {}),
52
+ ...(plan.first !== undefined ? { first: plan.first } : {}),
53
+ };
54
+ },
55
+ };
56
+ }
57
+
58
+ const COINS =
59
+ 'Bank coins are `{ denom, amountBaseUnits }` in base units (uixo ÷ 1,000,000 = IXO).';
60
+ const STATUSES =
61
+ 'Evaluation status is pending, approved, rejected, disputed, invalidated or flagged.';
62
+
63
+ const claimsKind = defineKind({
64
+ name: 'claims',
65
+ summary:
66
+ 'Claims an agent submitted (default: the user), newest first, with evaluation and payment status.',
67
+ explain: [
68
+ 'Each claim: claimId, collectionId, agent, submissionDate, `evaluation` (status, date) and `paymentsStatus` per payment leg (e.g. `approval: PAID`).',
69
+ STATUSES,
70
+ COINS,
71
+ '`totalCount` counts every matching claim; when `hasNextPage`, pass `endCursor` as `after` for the next page.',
72
+ ].join(' '),
73
+ source: 'blocksync',
74
+ list: true,
75
+ args: CORE_ARGS.claims,
76
+ example: { collectionId: '8250', first: 5 },
77
+ plan: (args, ctx) => blocksyncPlan({ kind: 'claims', ...args }, ctx),
78
+ });
79
+
80
+ const COUNTED = ' { totalCount pageInfo { ';
81
+
82
+ /**
83
+ * `claims` without its `totalCount`, which PostgreSQL computes by counting
84
+ * every matching claim: the page and `hasNextPage` only. What
85
+ * `get_account_overview` reads for its claims part. Not a `chain_lookup`
86
+ * kind.
87
+ */
88
+ export const claimsPage: KindDef = {
89
+ ...claimsKind,
90
+ plan(rawArgs, ctx) {
91
+ const plan = claimsKind.plan(rawArgs, ctx);
92
+ if ('invalid' in plan || plan.source !== 'blocksync') return plan;
93
+ return {
94
+ ...plan,
95
+ field: (alias) => plan.field(alias).replace(COUNTED, ' { pageInfo { '),
96
+ };
97
+ },
98
+ };
99
+
100
+ /** The core kinds, in catalogue order. */
101
+ export const CORE_KINDS: readonly KindDef[] = [
102
+ claimsKind,
103
+ defineKind({
104
+ name: 'claim',
105
+ summary:
106
+ 'One claim by id, with its current evaluation (status, oracle, reason, amount paid).',
107
+ explain: [
108
+ '`not_found` when the index has no claim with that id.',
109
+ STATUSES,
110
+ COINS,
111
+ "`subject` is `user` when the claim's agent is the user's address.",
112
+ ].join(' '),
113
+ source: 'blocksync',
114
+ list: false,
115
+ args: CORE_ARGS.claim,
116
+ example: {
117
+ claimId: 'bafkreido4unh2l34n5zy5sy3nhyc3nhih65eysmal5dlq6j56m3eecntfm',
118
+ },
119
+ plan: (args, ctx) => blocksyncPlan({ kind: 'claim', ...args }, ctx),
120
+ }),
121
+ defineKind({
122
+ name: 'claim_collection',
123
+ summary: 'One claim collection: claim counts, state and payment terms.',
124
+ explain: [
125
+ '`state` is open, paused or closed; quota, count, evaluated, approved, rejected and disputed count claims.',
126
+ '`payments` per leg (submission, evaluation, approval, rejection): the paying `account`, bank coins, cw20 amounts (`amountBaseUnits`, base units), cw1155 amounts (whole units, with token ids) and `oraclePayment` when an oracle is paid.',
127
+ COINS,
128
+ "`subject` is `user` when the collection's admin is the user.",
129
+ ].join(' '),
130
+ source: 'blocksync',
131
+ list: false,
132
+ args: CORE_ARGS.claim_collection,
133
+ example: { id: '8250' },
134
+ plan: (args, ctx) =>
135
+ blocksyncPlan({ kind: 'claim_collection', ...args }, ctx),
136
+ }),
137
+ defineKind({
138
+ name: 'claim_collections',
139
+ summary:
140
+ 'Claim collections by admin (default: the user) or by entity, newest start date first.',
141
+ explain: [
142
+ 'Each: id, entity, admin, protocol, start/end date, claim counts and state (open, paused, closed).',
143
+ 'A collection without a start date sorts first.',
144
+ 'With only `entity`, every collection of that entity whatever its admin, and no `subject`.',
145
+ ].join(' '),
146
+ source: 'blocksync',
147
+ list: true,
148
+ args: CORE_ARGS.claim_collections,
149
+ example: { first: 5 },
150
+ plan: (args, ctx) =>
151
+ blocksyncPlan({ kind: 'claim_collections', ...args }, ctx),
152
+ }),
153
+ defineKind({
154
+ name: 'entities',
155
+ summary:
156
+ 'Entities (DAOs, projects, protocols, assets…) an account owns (default: the user).',
157
+ explain: [
158
+ 'Each: id (did:ixo:entity:…), type, status, owner, created.',
159
+ 'Ordered by id as text: ids are hashes, so the order says nothing about age.',
160
+ "`status` is a number the entity's creator defines; the chain gives it no fixed meaning.",
161
+ ].join(' '),
162
+ source: 'blocksync',
163
+ list: true,
164
+ args: CORE_ARGS.entities,
165
+ example: { type: 'dao' },
166
+ plan: (args, ctx) => blocksyncPlan({ kind: 'entities', ...args }, ctx),
167
+ }),
168
+ defineKind({
169
+ name: 'entity',
170
+ summary:
171
+ 'One entity by DID: type, owner, controllers, accounts, linked entities and resources, services, settings.',
172
+ explain: [
173
+ 'Resources, services and settings show what and where (id, type, description, serviceEndpoint, mediaType), never their content.',
174
+ "`status` is a number the entity's creator defines.",
175
+ 'Ask it beside `did_document` for "what is did:ixo:entity:…".',
176
+ "`subject` is `user` when the entity's owner is the user.",
177
+ ].join(' '),
178
+ source: 'blocksync',
179
+ list: false,
180
+ args: CORE_ARGS.entity,
181
+ example: { id: 'did:ixo:entity:0123456789abcdef0123456789abcdef' },
182
+ plan: (args, ctx) => blocksyncPlan({ kind: 'entity', ...args }, ctx),
183
+ }),
184
+ defineKind({
185
+ name: 'did_document',
186
+ summary:
187
+ "A DID document (default: the user's DID): controllers, verification methods, linked resources.",
188
+ explain: [
189
+ 'Any did:ixo:… DID, an entity or an account.',
190
+ 'Verification methods show id, type, controller and the public key or blockchain account they hold.',
191
+ ].join(' '),
192
+ source: 'blocksync',
193
+ list: false,
194
+ args: CORE_ARGS.did_document,
195
+ example: {},
196
+ plan: (args, ctx) => blocksyncPlan({ kind: 'did_document', ...args }, ctx),
197
+ }),
198
+ defineKind({
199
+ name: 'token_balances',
200
+ summary:
201
+ 'IXO 1155 tokens (impact tokens, carbon credits…) an account holds (default: the user), largest first.',
202
+ explain: [
203
+ 'Each: tokenId, name, class, collection, amount, retired, contractAddress.',
204
+ 'IXO 1155 tokens have no decimals on chain: `amount` and `retired` are whole units.',
205
+ ].join(' '),
206
+ source: 'blocksync',
207
+ list: true,
208
+ args: CORE_ARGS.token_balances,
209
+ example: {},
210
+ plan: (args, ctx) =>
211
+ blocksyncPlan({ kind: 'token_balances', ...args }, ctx),
212
+ }),
213
+ defineKind({
214
+ name: 'transactions',
215
+ summary:
216
+ 'Transactions an account signed (default) or received, newest first, with each message summarised.',
217
+ explain: [
218
+ 'Each: hash, height, time, code, succeeded (code 0), memo and its first 5 messages (`messageCount` when there are more).',
219
+ 'Messages: MsgSend `{ from, to, amount }`, MsgTransferToken `{ from, to, tokens }` (whole units), claim messages `{ claimId, collectionId, status }`, an authz MsgExec as its first 5 inner messages, anything else as a short excerpt.',
220
+ '`received` matches the recipient of a message (or of the first message inside a MsgExec); MsgMultiSend outputs are not seen.',
221
+ COINS,
222
+ ].join(' '),
223
+ source: 'blocksync',
224
+ list: true,
225
+ args: CORE_ARGS.transactions,
226
+ example: { direction: 'received', first: 5 },
227
+ plan: (args, ctx) => blocksyncPlan({ kind: 'transactions', ...args }, ctx),
228
+ }),
229
+ defineKind({
230
+ name: 'transaction',
231
+ summary:
232
+ 'One transaction by hash, with up to 50 messages, its signers and fee.',
233
+ explain: [
234
+ 'As a row of `transactions`, plus up to 10 `signers` and the `fee`.',
235
+ COINS,
236
+ '`subject` is `user` when the user signed it.',
237
+ ].join(' '),
238
+ source: 'blocksync',
239
+ list: false,
240
+ args: CORE_ARGS.transaction,
241
+ example: {
242
+ hash: '9C1D5E4A7B3F20864D2E6A1C8B5F3D7E0A4C6B2D8F1E3A5C7B9D0F2E4A6C8B1D',
243
+ },
244
+ plan: (args, ctx) => blocksyncPlan({ kind: 'transaction', ...args }, ctx),
245
+ }),
246
+ ];