@ocap/resolver 1.28.8 → 1.29.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 (43) hide show
  1. package/esm/api.d.mts +24 -0
  2. package/esm/api.mjs +53 -0
  3. package/esm/hooks.d.mts +153 -0
  4. package/esm/hooks.mjs +267 -0
  5. package/esm/index.d.mts +201 -0
  6. package/esm/index.mjs +1327 -0
  7. package/esm/migration-chain.d.mts +52 -0
  8. package/esm/migration-chain.mjs +97 -0
  9. package/esm/package.mjs +5 -0
  10. package/esm/token-cache.d.mts +20 -0
  11. package/esm/token-cache.mjs +26 -0
  12. package/esm/token-distribution.d.mts +166 -0
  13. package/esm/token-distribution.mjs +241 -0
  14. package/esm/token-flow.d.mts +139 -0
  15. package/esm/token-flow.mjs +330 -0
  16. package/esm/types.d.mts +115 -0
  17. package/esm/types.mjs +1 -0
  18. package/lib/_virtual/rolldown_runtime.cjs +29 -0
  19. package/lib/api.cjs +54 -0
  20. package/lib/api.d.cts +24 -0
  21. package/lib/hooks.cjs +274 -0
  22. package/lib/hooks.d.cts +153 -0
  23. package/lib/index.cjs +1343 -0
  24. package/lib/index.d.cts +201 -0
  25. package/lib/migration-chain.cjs +99 -0
  26. package/lib/migration-chain.d.cts +52 -0
  27. package/lib/package.cjs +11 -0
  28. package/lib/token-cache.cjs +27 -0
  29. package/lib/token-cache.d.cts +20 -0
  30. package/lib/token-distribution.cjs +243 -0
  31. package/lib/token-distribution.d.cts +166 -0
  32. package/lib/token-flow.cjs +336 -0
  33. package/lib/token-flow.d.cts +139 -0
  34. package/lib/types.cjs +0 -0
  35. package/lib/types.d.cts +115 -0
  36. package/package.json +49 -21
  37. package/lib/api.js +0 -71
  38. package/lib/hooks.js +0 -339
  39. package/lib/index.js +0 -1486
  40. package/lib/migration-chain.js +0 -144
  41. package/lib/token-cache.js +0 -40
  42. package/lib/token-distribution.js +0 -358
  43. package/lib/token-flow.js +0 -445
@@ -0,0 +1,139 @@
1
+ import { IChainConfig, IFilter, IMigrationChain, IPipelineLogger, IResolverPaging, IStateDB, ITokenCache, TTransactionReceipt } from "./types.mjs";
2
+ import { BN } from "@ocap/util";
3
+
4
+ //#region src/token-flow.d.ts
5
+
6
+ /**
7
+ * Transfer item with BN value for calculation
8
+ */
9
+ interface ITransferItem {
10
+ address: string;
11
+ value: InstanceType<typeof BN>;
12
+ action?: string;
13
+ archived?: boolean;
14
+ }
15
+ /**
16
+ * Transfer flow with BN value
17
+ */
18
+ interface ITransferFlow {
19
+ from: string;
20
+ to: string;
21
+ value: InstanceType<typeof BN>;
22
+ hash: string;
23
+ }
24
+ /**
25
+ * Transfer flow result with string value
26
+ */
27
+ interface ITransferFlowResult {
28
+ from: string;
29
+ to: string;
30
+ value: string;
31
+ hash: string;
32
+ }
33
+ /**
34
+ * Risk check result
35
+ */
36
+ interface IRiskCheckResult {
37
+ isRisky: boolean;
38
+ reason?: string;
39
+ data: {
40
+ address?: string;
41
+ balance?: string | number;
42
+ transferIn?: string;
43
+ transferOut?: string;
44
+ accountCount: number;
45
+ txCount: number;
46
+ };
47
+ }
48
+ /**
49
+ * Parameters for verifyAccountRisk
50
+ */
51
+ interface IVerifyAccountRiskParams {
52
+ accountAddress: string;
53
+ tokenAddress: string;
54
+ accountLimit?: number;
55
+ txLimit?: number;
56
+ tolerance?: string;
57
+ }
58
+ /**
59
+ * Parameters for listTokenFlows
60
+ */
61
+ interface IListTokenFlowsParams {
62
+ accountAddress: string;
63
+ tokenAddress: string;
64
+ paging?: IResolverPaging;
65
+ depth?: number;
66
+ direction?: 'IN' | 'OUT';
67
+ }
68
+ /**
69
+ * Simplified transaction for token flow
70
+ */
71
+ interface ITokenFlowTx {
72
+ hash: string;
73
+ time: string;
74
+ receipts?: TTransactionReceipt[];
75
+ [key: string]: unknown;
76
+ }
77
+ /**
78
+ * Resolver interface for token flow operations
79
+ */
80
+ interface ITokenFlowResolver {
81
+ config: IChainConfig;
82
+ tokenCache: ITokenCache;
83
+ filter?: IFilter;
84
+ logger: IPipelineLogger;
85
+ statedb: IStateDB;
86
+ getMigrationChain: () => Promise<IMigrationChain>;
87
+ _getAllResults: <T>(type: string, fetcher: (paging: IResolverPaging) => Promise<{
88
+ transactions?: T[];
89
+ data?: T[];
90
+ }>, limit?: number) => Promise<T[]>;
91
+ listTransactions: (params: {
92
+ paging?: IResolverPaging;
93
+ accountFilter?: {
94
+ accounts: string[];
95
+ };
96
+ tokenFilter?: {
97
+ tokens: string[];
98
+ };
99
+ }, ctx?: Record<string, unknown>) => Promise<{
100
+ transactions: ITokenFlowTx[];
101
+ }>;
102
+ runAsLambda: <T>(fn: (txn: unknown) => Promise<T>, options?: {
103
+ retryLimit?: number;
104
+ }) => Promise<T>;
105
+ }
106
+ /**
107
+ * Parse transfer in/out list from transaction
108
+ * @param tx Transaction object
109
+ * @param tokenAddress Token address to filter by
110
+ * @returns Object containing transferInList and transferOutList
111
+ */
112
+ declare const getTransferList: (tx: ITokenFlowTx, tokenAddress: string) => {
113
+ transferInList: ITransferItem[];
114
+ transferOutList: ITransferItem[];
115
+ };
116
+ /**
117
+ * Parse transfer flow from transaction
118
+ * @param tx Transaction object
119
+ * @param tokenAddress Token address to filter by
120
+ * @returns Array of transfer flows
121
+ */
122
+ declare const getTransferFlow: (tx: ITokenFlowTx, tokenAddress: string) => ITransferFlow[];
123
+ declare const fixMigrateReceipts: (tx: ITokenFlowTx, resolver: ITokenFlowResolver) => Promise<void>;
124
+ declare const verifyAccountRisk: ({
125
+ accountAddress,
126
+ tokenAddress,
127
+ accountLimit,
128
+ txLimit,
129
+ tolerance
130
+ }: IVerifyAccountRiskParams, resolver: ITokenFlowResolver, ctx?: Record<string, unknown>) => Promise<IRiskCheckResult>;
131
+ declare const listTokenFlows: ({
132
+ accountAddress,
133
+ tokenAddress,
134
+ paging,
135
+ depth,
136
+ direction
137
+ }: IListTokenFlowsParams, resolver: ITokenFlowResolver, ctx?: Record<string, unknown>) => Promise<ITransferFlowResult[]>;
138
+ //#endregion
139
+ export { fixMigrateReceipts, getTransferFlow, getTransferList, listTokenFlows, verifyAccountRisk };
@@ -0,0 +1,330 @@
1
+ import { BN, fromTokenToUnit, isSameDid } from "@ocap/util";
2
+ import { Joi, schemas } from "@arcblock/validator";
3
+ import { CustomError } from "@ocap/util/lib/error";
4
+ import uniq from "lodash/uniq.js";
5
+ import { FORGE_TOKEN_HOLDER } from "@ocap/state/lib/states/tx";
6
+
7
+ //#region src/token-flow.ts
8
+ const ZERO = new BN(0);
9
+ const paramsSchema = Joi.object({
10
+ accountAddress: schemas.tokenHolder.required(),
11
+ tokenAddress: Joi.DID().prefix().role("ROLE_TOKEN").required(),
12
+ resolver: Joi.object().required()
13
+ });
14
+ /**
15
+ * Parse transfer in/out list from transaction
16
+ * @param tx Transaction object
17
+ * @param tokenAddress Token address to filter by
18
+ * @returns Object containing transferInList and transferOutList
19
+ */
20
+ const getTransferList = (tx, tokenAddress) => {
21
+ const transferInList = [];
22
+ const transferOutList = [];
23
+ for (const receipt of tx.receipts || []) {
24
+ const changes = receipt.changes.filter((item) => item.target === tokenAddress && item.value !== "0");
25
+ for (const change of changes) {
26
+ const value = new BN(change.value);
27
+ const item = {
28
+ address: receipt.address,
29
+ value: value.abs(),
30
+ action: change.action
31
+ };
32
+ if (value.lt(ZERO)) transferOutList.push(item);
33
+ else transferInList.push(item);
34
+ }
35
+ }
36
+ return {
37
+ transferInList,
38
+ transferOutList
39
+ };
40
+ };
41
+ /**
42
+ * Parse transfer flow from transaction
43
+ * @param tx Transaction object
44
+ * @param tokenAddress Token address to filter by
45
+ * @returns Array of transfer flows
46
+ */
47
+ const getTransferFlow = (tx, tokenAddress) => {
48
+ const { transferInList, transferOutList } = getTransferList(tx, tokenAddress);
49
+ const txTransfers = [];
50
+ for (const outItem of transferOutList) {
51
+ if (outItem.archived) continue;
52
+ const matchedInItem = transferInList.find((x) => x.value.eq(outItem.value));
53
+ if (matchedInItem) {
54
+ txTransfers.push({
55
+ from: outItem.address,
56
+ to: matchedInItem.address,
57
+ value: outItem.value,
58
+ hash: tx.hash
59
+ });
60
+ matchedInItem.archived = true;
61
+ outItem.archived = true;
62
+ continue;
63
+ }
64
+ for (const inItem of transferInList) {
65
+ if (inItem.archived) continue;
66
+ if (outItem.archived) continue;
67
+ if (outItem.value.gt(inItem.value)) {
68
+ txTransfers.push({
69
+ from: outItem.address,
70
+ to: inItem.address,
71
+ value: inItem.value,
72
+ hash: tx.hash
73
+ });
74
+ inItem.archived = true;
75
+ outItem.value = outItem.value.sub(inItem.value);
76
+ continue;
77
+ }
78
+ if (outItem.value.lt(inItem.value)) {
79
+ txTransfers.push({
80
+ from: outItem.address,
81
+ to: inItem.address,
82
+ value: outItem.value,
83
+ hash: tx.hash
84
+ });
85
+ outItem.archived = true;
86
+ inItem.value = inItem.value.sub(outItem.value);
87
+ continue;
88
+ }
89
+ if (outItem.value.eq(inItem.value)) {
90
+ txTransfers.push({
91
+ from: outItem.address,
92
+ to: inItem.address,
93
+ value: inItem.value,
94
+ hash: tx.hash
95
+ });
96
+ inItem.archived = true;
97
+ outItem.archived = true;
98
+ }
99
+ }
100
+ }
101
+ return txTransfers;
102
+ };
103
+ const getVaultAccounts = (config) => {
104
+ return Object.values(config.vaults).flat().concat(FORGE_TOKEN_HOLDER);
105
+ };
106
+ const getInitialBalance = (address, config) => {
107
+ const account = config?.accounts?.find((x) => isSameDid(x.address, address));
108
+ return account ? fromTokenToUnit(account.balance ?? 0) : ZERO;
109
+ };
110
+ const getBalance = async (address, tokenAddress, { resolver, txn }) => {
111
+ const state = await resolver.statedb.account.get(address, {
112
+ txn,
113
+ traceMigration: false
114
+ });
115
+ if (!state) throw new CustomError("INVALID_REQUEST", `Invalid address ${address}`);
116
+ return state.tokens[tokenAddress] || 0;
117
+ };
118
+ const fixMigrateReceipts = async (tx, resolver) => {
119
+ const migrationChain = await resolver.getMigrationChain();
120
+ const txTime = new Date(tx.time);
121
+ tx.receipts?.forEach((receipt) => {
122
+ receipt.address = migrationChain.findAddressAtTime(receipt.address, txTime);
123
+ });
124
+ };
125
+ const verifyAccountRisk = async ({ accountAddress, tokenAddress, accountLimit = 400, txLimit = 1e4, tolerance = "0.0000000001" }, resolver, ctx = {}) => {
126
+ const validation = paramsSchema.validate({
127
+ accountAddress,
128
+ tokenAddress,
129
+ resolver
130
+ });
131
+ if (validation.error) throw new CustomError("INVALID_PARAMS", validation.error.message);
132
+ const { logger } = resolver;
133
+ const checkedAccounts = /* @__PURE__ */ new Map();
134
+ const checkedTx = /* @__PURE__ */ new Map();
135
+ const toleranceUnit = fromTokenToUnit(tolerance, (await resolver.tokenCache.get(tokenAddress))?.decimal);
136
+ const vaultAccounts = getVaultAccounts(resolver.config);
137
+ const accountQueue = [[{
138
+ address: accountAddress,
139
+ chain: []
140
+ }]];
141
+ const execute = async (depth, txn) => {
142
+ const queue = accountQueue[depth];
143
+ for (let i = 0; i < queue.length; i++) {
144
+ if (checkedAccounts.size >= accountLimit) {
145
+ logger.warn("Account risk check reached max account size limit", {
146
+ address: accountAddress,
147
+ tokenAddress,
148
+ accountCount: checkedAccounts.size,
149
+ txCount: checkedTx.size,
150
+ depth,
151
+ accountLimit,
152
+ txLimit,
153
+ tolerance
154
+ });
155
+ return {
156
+ isRisky: false,
157
+ reason: "MAX_ACCOUNT_SIZE_LIMIT",
158
+ data: {
159
+ accountCount: checkedAccounts.size,
160
+ txCount: checkedTx.size
161
+ }
162
+ };
163
+ }
164
+ const { address, chain } = queue[i];
165
+ chain.push(address);
166
+ if (checkedAccounts.has(address)) continue;
167
+ const trustedConfig = await resolver.filter?.getTrustedAccountConfig?.(address);
168
+ if (trustedConfig && !trustedConfig.tolerance) {
169
+ checkedAccounts.set(address, true);
170
+ continue;
171
+ }
172
+ let balance = 0;
173
+ let transactions = [];
174
+ try {
175
+ [balance, transactions] = await Promise.all([getBalance(address, tokenAddress, {
176
+ resolver,
177
+ txn
178
+ }), resolver._getAllResults("transactions", (paging) => resolver.listTransactions({
179
+ paging,
180
+ accountFilter: { accounts: [address] }
181
+ }, ctx), txLimit)]);
182
+ } catch (e) {
183
+ if (e?.code === "EXCEED_LIMIT") {
184
+ logger.warn("Skip checking account cause tx count exceeding limit", {
185
+ address,
186
+ txLimit
187
+ });
188
+ checkedAccounts.set(address, true);
189
+ continue;
190
+ }
191
+ throw e;
192
+ }
193
+ let transferIn = getInitialBalance(address, resolver.config);
194
+ let transferOut = ZERO;
195
+ for (const tx of transactions) {
196
+ if (!checkedTx.has(tx.hash)) {
197
+ await fixMigrateReceipts(tx, resolver);
198
+ checkedTx.set(tx.hash, getTransferList(tx, tokenAddress));
199
+ }
200
+ const { transferInList, transferOutList } = checkedTx.get(tx.hash);
201
+ const transferInAmount = transferInList.filter((item) => isSameDid(item.address, address)).map((item) => item.value).reduce((prev, cur) => prev.add(cur), ZERO);
202
+ const transferOutAmount = transferOutList.filter((item) => isSameDid(item.address, address)).map((item) => item.value).reduce((prev, cur) => prev.add(cur), ZERO);
203
+ transferIn = transferIn.add(transferInAmount);
204
+ transferOut = transferOut.add(transferOutAmount);
205
+ if (transferInAmount.gt(ZERO)) {
206
+ if (!accountQueue[depth + 1]) accountQueue[depth + 1] = [];
207
+ const accountsToQueue = transferOutList.filter((item) => {
208
+ if (checkedAccounts.has(item.address)) return false;
209
+ if (schemas.tokenHolder.validate(item.address).error) return false;
210
+ if (vaultAccounts.includes(item.address)) return false;
211
+ if (["gas", "fee"].includes(item.action || "")) return false;
212
+ return true;
213
+ }).map((item) => item.address);
214
+ accountQueue[depth + 1].push(...uniq(accountsToQueue).map((x) => ({
215
+ address: x,
216
+ chain: chain.concat()
217
+ })));
218
+ }
219
+ }
220
+ checkedAccounts.set(address, true);
221
+ const diff = transferIn.sub(transferOut).sub(new BN(balance)).add(fromTokenToUnit(trustedConfig?.tolerance || 0));
222
+ if (diff.abs().gt(toleranceUnit)) {
223
+ const data = {
224
+ address: chain.join("->"),
225
+ balance,
226
+ transferIn: transferIn.toString(),
227
+ transferOut: transferOut.toString(),
228
+ accountCount: checkedAccounts.size,
229
+ txCount: checkedTx.size
230
+ };
231
+ logger.warn("Account balance does not match transfer records", {
232
+ ...data,
233
+ sourceAccount: accountAddress,
234
+ tokenAddress,
235
+ diff: diff.toString(),
236
+ depth,
237
+ accountLimit,
238
+ txLimit,
239
+ tolerance
240
+ });
241
+ return {
242
+ isRisky: true,
243
+ reason: "INVALID_BALANCE",
244
+ data
245
+ };
246
+ }
247
+ }
248
+ };
249
+ for (let depth = 0; depth < accountQueue.length; depth++) {
250
+ let isExecuted = false;
251
+ const result = await resolver.runAsLambda((txn) => {
252
+ if (isExecuted) throw new CustomError("INVALID_REQUEST", "verifyAccountRisk should not retry");
253
+ isExecuted = true;
254
+ return execute(depth, txn);
255
+ }, { retryLimit: 0 });
256
+ if (result) return result;
257
+ }
258
+ logger.info("Account risk check completed", {
259
+ address: accountAddress,
260
+ tokenAddress,
261
+ accountCount: checkedAccounts.size,
262
+ txCount: checkedTx.size,
263
+ depth: accountQueue.length,
264
+ accountLimit,
265
+ txLimit,
266
+ tolerance
267
+ });
268
+ return {
269
+ isRisky: false,
270
+ data: {
271
+ accountCount: checkedAccounts.size,
272
+ txCount: checkedTx.size
273
+ }
274
+ };
275
+ };
276
+ const listTokenFlows = async ({ accountAddress, tokenAddress, paging = {}, depth = 2, direction = "OUT" }, resolver, ctx = {}) => {
277
+ const { error } = paramsSchema.validate({
278
+ accountAddress,
279
+ tokenAddress,
280
+ resolver
281
+ });
282
+ if (error) throw new CustomError("INVALID_PARAMS", error.message);
283
+ const minAmount = fromTokenToUnit(1, (await resolver.tokenCache.get(tokenAddress))?.decimal || 18);
284
+ const maxAccountSize = Math.min(200, paging.size || 200);
285
+ const maxDepth = Math.min(5, depth);
286
+ const vaultAccounts = getVaultAccounts(resolver.config);
287
+ const tokenFlows = [];
288
+ const checkedAccounts = /* @__PURE__ */ new Map();
289
+ const checkedTx = /* @__PURE__ */ new Map();
290
+ let curDepth = 1;
291
+ const depthQueue = { [curDepth]: [accountAddress] };
292
+ while (depthQueue[curDepth]?.length && curDepth <= maxDepth && checkedAccounts.size < maxAccountSize) {
293
+ for (const address of depthQueue[curDepth]) {
294
+ if (checkedAccounts.has(address)) continue;
295
+ if (schemas.tokenHolder.validate(address).error) continue;
296
+ const transactions = await resolver._getAllResults("transactions", (page) => resolver.listTransactions({
297
+ paging: page,
298
+ accountFilter: { accounts: [address] },
299
+ tokenFilter: { tokens: [tokenAddress] }
300
+ }, ctx));
301
+ let accountsToQueue = [];
302
+ for (const tx of transactions) {
303
+ if (!checkedTx.has(tx.hash)) {
304
+ await fixMigrateReceipts(tx, resolver);
305
+ checkedTx.set(tx.hash, getTransferFlow(tx, tokenAddress));
306
+ }
307
+ const txTransfers = checkedTx.get(tx.hash).filter((item) => {
308
+ if (direction === "OUT" && item.from !== address) return false;
309
+ if (direction === "IN" && item.to !== address) return false;
310
+ if (item.value.lt(minAmount)) return false;
311
+ return true;
312
+ });
313
+ tokenFlows.push(...txTransfers.map((item) => ({
314
+ ...item,
315
+ value: item.value.toString()
316
+ })));
317
+ accountsToQueue = accountsToQueue.concat(txTransfers.map((item) => direction === "IN" ? item.from : item.to).filter((item) => !vaultAccounts.includes(item)));
318
+ }
319
+ checkedAccounts.set(address, true);
320
+ if (checkedAccounts.size >= maxAccountSize) break;
321
+ if (!depthQueue[curDepth + 1]) depthQueue[curDepth + 1] = [];
322
+ depthQueue[curDepth + 1].push(...uniq(accountsToQueue));
323
+ }
324
+ curDepth++;
325
+ }
326
+ return tokenFlows;
327
+ };
328
+
329
+ //#endregion
330
+ export { fixMigrateReceipts, getTransferFlow, getTransferList, listTokenFlows, verifyAccountRisk };
@@ -0,0 +1,115 @@
1
+ import { Address, BN, DirectionMap, Hash, IAccountState, IAddressArgs, IAny, IAssetFactoryState, IAssetState, IBalanceTable, IChainConfig, IChainConfig as IChainConfig$1, IChainState, IDelegateState, IEvidenceState, IExecutedContext, IForeignToken, IGetAccountStateArgs, IGetAccountTokensArgs, IIndexDB, IIndexDB as IIndexDB$1, IIndexTable, IIndexTable as IIndexTable$1, IListAccountsResult, IListAssetsResult, IListDelegationsResult, IListFactoriesResult, IListRollupBlocksResult, IListRollupValidatorsResult, IListRollupsResult, IListStakesResult, IListTokenFactoriesResult, IListTokensResult, IListTransactionsResult, IOperationContext, IPipelineLogger, IPipelineLogger as IPipelineLogger$1, IResolver, IResolverAccountState, IResolverChainInfo, IResolverContext, IResolverContext as IResolverContext$1, IResolverFactoryState, IResolverForgeStats, IResolverListAccountsResult, IResolverListAssetsResult, IResolverListDelegationsResult, IResolverListFactoriesResult, IResolverListRollupBlocksResult, IResolverListRollupValidatorsResult, IResolverListRollupsResult, IResolverListStakesResult, IResolverListTokenFactoriesResult, IResolverListTokensResult, IResolverListTransactionsResult, IResolverNetInfo, IResolverNodeInfo, IResolverPaging, IResolverPaging as IResolverPaging$1, IResolverRollupState, IResolverStakeState, IResolverTransaction, IResolverTxItxJson, IResolverValidatorsInfo, IRollupBlock, IRollupState, IRollupValidator, IStakeState, IStateContext, IStateDB, IStateDB as IStateDB$1, IStateTable, IStateTable as IStateTable$1, ITokenConfig, ITokenFactoryState, ITokenFlowsResult, ITokenInfo, ITokenInfo as ITokenInfo$1, ITokenMetadata, ITokenState, ITransactionConfig, ITxGasConfig, ITxStakeConfig, ITxState, IVaultsConfig, IndexTableTypeMap, Promisable, TAccountFilter, TAccountToken, TAddressFilter, TAssetFilter, TDelegationFilter, TFactoryFilter, TIndexedAccountState, TIndexedAssetState, TIndexedDelegationState, TIndexedFactoryState, TIndexedRollupBlock, TIndexedRollupState, TIndexedRollupValidator, TIndexedStakeState, TIndexedTokenFactoryState, TIndexedTokenState, TIndexedTokenState as TIndexedTokenState$1, TIndexedTransaction, TPage, TPageInfo, TPageOrder, TRangeFilter, TReceiptChange, TRequestEstimateGas, TRequestGetEvidenceState, TRequestGetRollupBlock, TRequestGetTokenDistribution, TRequestGetTx, TRequestListAssetTransactions, TRequestListAssets, TRequestListDelegations, TRequestListFactories, TRequestListRollupBlocks, TRequestListRollupValidators, TRequestListRollups, TRequestListStakes, TRequestListTokenFactories, TRequestListTokenFlows, TRequestListTokens, TRequestListTopAccounts, TRequestListTransactions, TRequestSearch, TRequestVerifyAccountRisk, TRollupFilter, TSearchResult, TStakeFilter, TTimeFilter, TTokenDistribution, TTokenFactoryFilter, TTokenFilter, TTokenMeta, TTransactionReceipt, TTxFilter, TTypeFilter, TValidatorFilter, TValidityFilter, TVerifyAccountRiskResult, TokenBalanceMap, ValidityMap } from "@ocap/types";
2
+
3
+ //#region src/types.d.ts
4
+
5
+ /**
6
+ * Flexible StateDB type that supports dynamic table access
7
+ */
8
+ type FlexibleStateDB = IStateDB$1 & {
9
+ [key: string]: IStateTable$1<unknown>;
10
+ };
11
+ /**
12
+ * Flexible IndexDB type that supports dynamic table access
13
+ */
14
+ type FlexibleIndexDB = IIndexDB$1 & {
15
+ [key: string]: IIndexTable$1<unknown> | ((...args: unknown[]) => Promise<unknown>);
16
+ };
17
+ /**
18
+ * Data object for encoded data fields (typeUrl + value)
19
+ */
20
+ interface IDataObject {
21
+ type_url?: string;
22
+ typeUrl?: string;
23
+ value?: string;
24
+ type?: string;
25
+ [key: string]: unknown;
26
+ }
27
+ /**
28
+ * Delegation operation
29
+ */
30
+ interface IDelegationOp {
31
+ key: string;
32
+ value: {
33
+ limit?: {
34
+ tokens?: ITokenInfo$1[];
35
+ };
36
+ [key: string]: unknown;
37
+ };
38
+ }
39
+ /**
40
+ * Chunk iterator for paginated data fetching
41
+ */
42
+ interface IChunkIterator<T> {
43
+ next: () => Promise<T[]>;
44
+ done: boolean;
45
+ }
46
+ /**
47
+ * Parameters for list chunks operation
48
+ */
49
+ interface IListChunksParams {
50
+ total: number;
51
+ concurrency?: number;
52
+ chunkSize?: number;
53
+ pageSize?: number;
54
+ timeKey: string;
55
+ dataKey: string;
56
+ }
57
+ /**
58
+ * Generic paginated result
59
+ */
60
+ interface IPaginatedResult<T> {
61
+ paging?: IResolverPaging$1;
62
+ [key: string]: T[] | IResolverPaging$1 | unknown;
63
+ }
64
+ /**
65
+ * Filter interface for risk verification
66
+ */
67
+ interface IFilter {
68
+ getTrustedAccountConfig?: (address: string) => Promise<ITrustedAccountConfig | null>;
69
+ [key: string]: any;
70
+ }
71
+ /**
72
+ * Trusted account configuration
73
+ */
74
+ interface ITrustedAccountConfig {
75
+ tolerance?: string | number;
76
+ [key: string]: unknown;
77
+ }
78
+ /**
79
+ * Resolver constructor parameters
80
+ */
81
+ interface IResolverParams {
82
+ statedb: IStateDB$1;
83
+ indexdb: IIndexDB$1;
84
+ config: IChainConfig$1;
85
+ filter?: IFilter;
86
+ validateTokenConfig?: boolean;
87
+ logger?: IPipelineLogger$1;
88
+ }
89
+ /**
90
+ * Get state parameters
91
+ */
92
+ interface IGetStateParams {
93
+ table: string;
94
+ id: string;
95
+ dataKey?: string | string[] | null;
96
+ extraParams?: Record<string, unknown>;
97
+ onRead?: (state: any) => any;
98
+ expandContext?: boolean;
99
+ ctx?: IResolverContext$1;
100
+ }
101
+ /**
102
+ * Token cache interface
103
+ */
104
+ interface ITokenCache {
105
+ get: (address: string) => Promise<TIndexedTokenState$1 | null>;
106
+ set: (address: string, token: TIndexedTokenState$1) => void;
107
+ }
108
+ /**
109
+ * Migration chain interface
110
+ */
111
+ interface IMigrationChain {
112
+ findAddressAtTime: (address: string, time: Date) => string;
113
+ }
114
+ //#endregion
115
+ export { type Address, type BN, type DirectionMap, FlexibleIndexDB, FlexibleStateDB, type Hash, type IAccountState, type IAddressArgs, type IAny, type IAssetFactoryState, type IAssetState, type IBalanceTable, type IChainConfig, type IChainState, IChunkIterator, IDataObject, type IDelegateState, IDelegationOp, type IEvidenceState, type IExecutedContext, IFilter, type IForeignToken, type IGetAccountStateArgs, type IGetAccountTokensArgs, IGetStateParams, type IIndexDB, type IIndexTable, type IListAccountsResult, type IListAssetsResult, IListChunksParams, type IListDelegationsResult, type IListFactoriesResult, type IListRollupBlocksResult, type IListRollupValidatorsResult, type IListRollupsResult, type IListStakesResult, type IListTokenFactoriesResult, type IListTokensResult, type IListTransactionsResult, IMigrationChain, type IOperationContext, IPaginatedResult, type IPipelineLogger, type IResolver, type IResolverAccountState, type IResolverChainInfo, type IResolverContext, type IResolverFactoryState, type IResolverForgeStats, type IResolverListAccountsResult, type IResolverListAssetsResult, type IResolverListDelegationsResult, type IResolverListFactoriesResult, type IResolverListRollupBlocksResult, type IResolverListRollupValidatorsResult, type IResolverListRollupsResult, type IResolverListStakesResult, type IResolverListTokenFactoriesResult, type IResolverListTokensResult, type IResolverListTransactionsResult, type IResolverNetInfo, type IResolverNodeInfo, type IResolverPaging, IResolverParams, type IResolverRollupState, type IResolverStakeState, type IResolverTransaction, type IResolverTxItxJson, type IResolverValidatorsInfo, type IRollupBlock, type IRollupState, type IRollupValidator, type IStakeState, type IStateContext, type IStateDB, type IStateTable, ITokenCache, type ITokenConfig, type ITokenFactoryState, type ITokenFlowsResult, type ITokenInfo, type ITokenMetadata, type ITokenState, type ITransactionConfig, ITrustedAccountConfig, type ITxGasConfig, type ITxStakeConfig, type ITxState, type IVaultsConfig, type IndexTableTypeMap, type Promisable, type TAccountFilter, type TAccountToken, type TAddressFilter, type TAssetFilter, type TDelegationFilter, type TFactoryFilter, type TIndexedAccountState, type TIndexedAssetState, type TIndexedDelegationState, type TIndexedFactoryState, type TIndexedRollupBlock, type TIndexedRollupState, type TIndexedRollupValidator, type TIndexedStakeState, type TIndexedTokenFactoryState, type TIndexedTokenState, type TIndexedTransaction, type TPage, type TPageInfo, type TPageOrder, type TRangeFilter, type TReceiptChange, type TRequestEstimateGas, type TRequestGetEvidenceState, type TRequestGetRollupBlock, type TRequestGetTokenDistribution, type TRequestGetTx, type TRequestListAssetTransactions, type TRequestListAssets, type TRequestListDelegations, type TRequestListFactories, type TRequestListRollupBlocks, type TRequestListRollupValidators, type TRequestListRollups, type TRequestListStakes, type TRequestListTokenFactories, type TRequestListTokenFlows, type TRequestListTokens, type TRequestListTopAccounts, type TRequestListTransactions, type TRequestSearch, type TRequestVerifyAccountRisk, type TRollupFilter, type TSearchResult, type TStakeFilter, type TTimeFilter, type TTokenDistribution, type TTokenFactoryFilter, type TTokenFilter, type TTokenMeta, type TTransactionReceipt, type TTxFilter, type TTypeFilter, type TValidatorFilter, type TValidityFilter, type TVerifyAccountRiskResult, type TokenBalanceMap, type ValidityMap };
package/esm/types.mjs ADDED
@@ -0,0 +1 @@
1
+ export { };
@@ -0,0 +1,29 @@
1
+ //#region rolldown:runtime
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __copyProps = (to, from, except, desc) => {
9
+ if (from && typeof from === "object" || typeof from === "function") {
10
+ for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
11
+ key = keys[i];
12
+ if (!__hasOwnProp.call(to, key) && key !== except) {
13
+ __defProp(to, key, {
14
+ get: ((k) => from[k]).bind(null, key),
15
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
16
+ });
17
+ }
18
+ }
19
+ }
20
+ return to;
21
+ };
22
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
23
+ value: mod,
24
+ enumerable: true
25
+ }) : target, mod));
26
+
27
+ //#endregion
28
+
29
+ exports.__toESM = __toESM;
package/lib/api.cjs ADDED
@@ -0,0 +1,54 @@
1
+ const require_rolldown_runtime = require('./_virtual/rolldown_runtime.cjs');
2
+ let _arcblock_nft_display = require("@arcblock/nft-display");
3
+ let express = require("express");
4
+
5
+ //#region src/api.ts
6
+ function createAPIHandler({ resolver }) {
7
+ const router = (0, express.Router)();
8
+ router.get("/token/display", async (req, res) => {
9
+ const { address } = req.query;
10
+ if (!address) return res.status(400).json({ error: "address is required" });
11
+ const token = await resolver.getTokenState({ address });
12
+ if (!token) return res.status(400).json({ error: "token not found" });
13
+ let iconUri = "";
14
+ if (token.icon) {
15
+ let iconWidth = 40;
16
+ let iconHeight = 40;
17
+ const viewBoxMatch = token.icon.match(/viewBox\s*=\s*["']([^"']+)["']/i);
18
+ if (viewBoxMatch) {
19
+ const viewBoxValues = viewBoxMatch[1].split(/\s+/);
20
+ if (viewBoxValues.length >= 4) {
21
+ iconWidth = +viewBoxValues[2] || iconWidth;
22
+ iconHeight = +viewBoxValues[3] || iconHeight;
23
+ }
24
+ }
25
+ const fixedSvg = token.icon.replace(/<svg([^>]*)>/, `<svg$1 width="${iconWidth}" height="${iconHeight}">`);
26
+ iconUri = `data:image/svg+xml;base64,${Buffer.from(fixedSvg).toString("base64")}`;
27
+ }
28
+ const svg = (0, _arcblock_nft_display.getSvg)({
29
+ color: (0, _arcblock_nft_display.getNftBGColorFromDid)(address),
30
+ did: address,
31
+ variant: "app-passport",
32
+ verifiable: true,
33
+ chain: "arcblock",
34
+ header: {
35
+ icon: iconUri,
36
+ name: token.symbol
37
+ },
38
+ issuer: {
39
+ name: token.symbol,
40
+ icon: iconUri
41
+ },
42
+ extra: {
43
+ key: "Name",
44
+ value: token.name
45
+ }
46
+ });
47
+ res.setHeader("Content-Type", "image/svg+xml");
48
+ res.send(svg);
49
+ });
50
+ return router;
51
+ }
52
+
53
+ //#endregion
54
+ exports.createAPIHandler = createAPIHandler;