@distrohelena/canton-explorer 0.1.4 → 0.1.6
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 +32 -0
- package/dist/public/assets/DebuggerView-Mk6TEUJB.js +5 -0
- package/dist/public/assets/abap-08VXUWAP.js +1 -0
- package/dist/public/assets/apex-BWPQTe0t.js +1 -0
- package/dist/public/assets/azcli-Bc_sGQ0U.js +1 -0
- package/dist/public/assets/bat-i0X4ZdIN.js +1 -0
- package/dist/public/assets/bicep-B5-_aFwp.js +2 -0
- package/dist/public/assets/cameligo-DMUM7wLl.js +1 -0
- package/dist/public/assets/clojure-Cm7r79vr.js +1 -0
- package/dist/public/assets/codicon-ngg6Pgfi.ttf +0 -0
- package/dist/public/assets/coffee-Ba7i2nA0.js +1 -0
- package/dist/public/assets/cpp-C7h46wYY.js +1 -0
- package/dist/public/assets/csharp-BKxtCVv1.js +1 -0
- package/dist/public/assets/csp-bTuwJoIa.js +1 -0
- package/dist/public/assets/css-DIMkf-bt.js +3 -0
- package/dist/public/assets/cssMode-Ce-rlOrP.js +1 -0
- package/dist/public/assets/cypher-CVaqCwHa.js +1 -0
- package/dist/public/assets/dart-onAF5SnQ.js +1 -0
- package/dist/public/assets/dockerfile-DZFCIeNp.js +1 -0
- package/dist/public/assets/ecl-D05T4iGw.js +1 -0
- package/dist/public/assets/editor-Br_kD0ds.css +1 -0
- package/dist/public/assets/editor.api2-7H_iQTr0.js +872 -0
- package/dist/public/assets/elixir-6RTg0lbw.js +1 -0
- package/dist/public/assets/flow9-C5_-GSwl.js +1 -0
- package/dist/public/assets/freemarker2-B-DvnnHs.js +3 -0
- package/dist/public/assets/fsharp-C8Ef5oNN.js +1 -0
- package/dist/public/assets/go-C-y9NEjX.js +1 -0
- package/dist/public/assets/graphql-fmXr3nnJ.js +1 -0
- package/dist/public/assets/handlebars-CME0Fldi.js +1 -0
- package/dist/public/assets/hcl-CpzslTdj.js +1 -0
- package/dist/public/assets/html-Beb3lxWO.js +1 -0
- package/dist/public/assets/htmlMode-CAgp27Dj.js +1 -0
- package/dist/public/assets/index-CucRixYI.css +1 -0
- package/dist/public/assets/index-Dn15ZYDU.js +1 -0
- package/dist/public/assets/ini-sBoK_t0W.js +1 -0
- package/dist/public/assets/java-BEtHBSE6.js +1 -0
- package/dist/public/assets/javascript-DdcWrUzt.js +1 -0
- package/dist/public/assets/jsonMode-BCddWWWg.js +7 -0
- package/dist/public/assets/julia-Bri6UV-V.js +1 -0
- package/dist/public/assets/kotlin-BOotOW0E.js +1 -0
- package/dist/public/assets/less-B9JPFI3C.js +2 -0
- package/dist/public/assets/lexon-CfSJPG6W.js +1 -0
- package/dist/public/assets/liquid-DmF9SgC3.js +1 -0
- package/dist/public/assets/lspLanguageFeatures-D7zEWtOG.js +4 -0
- package/dist/public/assets/lua-CsQS60Ue.js +1 -0
- package/dist/public/assets/m3-D-oSqn_W.js +1 -0
- package/dist/public/assets/markdown-Cimd5fb3.js +1 -0
- package/dist/public/assets/mdx-PwCfoB0S.js +1 -0
- package/dist/public/assets/mips-CIPQ_RoX.js +1 -0
- package/dist/public/assets/monaco-runtime-Bkgn_wG8.js +6 -0
- package/dist/public/assets/monaco.contribution-B2Ohh6Li.js +2 -0
- package/dist/public/assets/msdax-DauUninz.js +1 -0
- package/dist/public/assets/mysql-SOo6toE5.js +1 -0
- package/dist/public/assets/objective-c-FvmIjYaQ.js +1 -0
- package/dist/public/assets/pascal-DrH0SRf2.js +1 -0
- package/dist/public/assets/pascaligo-D-ptJ9y-.js +1 -0
- package/dist/public/assets/perl-oz_6vUea.js +1 -0
- package/dist/public/assets/pgsql-DTj74zXo.js +1 -0
- package/dist/public/assets/php-nr791fC2.js +1 -0
- package/dist/public/assets/pla-CopQ2nXW.js +1 -0
- package/dist/public/assets/postiats-43DmfD33.js +1 -0
- package/dist/public/assets/powerquery-D3hlyOfw.js +1 -0
- package/dist/public/assets/powershell-DmHpPYUd.js +1 -0
- package/dist/public/assets/protobuf-C531GsRP.js +2 -0
- package/dist/public/assets/pug-Z5eAx3Zn.js +1 -0
- package/dist/public/assets/python-pS1EqvyQ.js +1 -0
- package/dist/public/assets/qsharp-DkqhCAOL.js +1 -0
- package/dist/public/assets/r-BwWrilGY.js +1 -0
- package/dist/public/assets/razor-CZ2fK_eC.js +1 -0
- package/dist/public/assets/redis-ClamHrr6.js +1 -0
- package/dist/public/assets/redshift-DT7zqm-g.js +1 -0
- package/dist/public/assets/restructuredtext-BYgofb2h.js +1 -0
- package/dist/public/assets/ruby-DezsRK8O.js +1 -0
- package/dist/public/assets/rust-DdL9SqIa.js +1 -0
- package/dist/public/assets/sb-CcwsVR0C.js +1 -0
- package/dist/public/assets/scala-DHpiXF5c.js +1 -0
- package/dist/public/assets/scheme-BeGwcela.js +1 -0
- package/dist/public/assets/scss-gp-XZpBa.js +3 -0
- package/dist/public/assets/shell-CC2rA5mh.js +1 -0
- package/dist/public/assets/solidity-BEEn4gHE.js +1 -0
- package/dist/public/assets/sophia-CRfGWb83.js +1 -0
- package/dist/public/assets/sparql-D_Lu-MrJ.js +1 -0
- package/dist/public/assets/sql-NEE52Syq.js +1 -0
- package/dist/public/assets/st-DbInun42.js +1 -0
- package/dist/public/assets/swift-Bxkupp3x.js +1 -0
- package/dist/public/assets/systemverilog-Bz4Y3fRF.js +1 -0
- package/dist/public/assets/tcl-DISqw1ZD.js +1 -0
- package/dist/public/assets/tsMode-06H9OqyC.js +11 -0
- package/dist/public/assets/twig-De2hgUGE.js +1 -0
- package/dist/public/assets/typescript-DS7X1pib.js +1 -0
- package/dist/public/assets/typespec-B8J7ngcE.js +1 -0
- package/dist/public/assets/vb-DV3o63ZY.js +1 -0
- package/dist/public/assets/wgsl-DpFanUEy.js +298 -0
- package/dist/public/assets/workers-D4g7l69J.js +1 -0
- package/dist/public/assets/xml-Br0rHxWi.js +1 -0
- package/dist/public/assets/yaml-qASkMRyN.js +1 -0
- package/dist/public/index.html +2 -2
- package/dist/src/api/nodes.controller.d.ts +2 -2
- package/dist/src/api/nodes.controller.js +20 -8
- package/dist/src/api/nodes.controller.js.map +1 -1
- package/dist/src/cache/node-cache.service.js +23 -9
- package/dist/src/cache/node-cache.service.js.map +1 -1
- package/dist/src/debugger/debugger.service.d.ts +2 -0
- package/dist/src/debugger/debugger.service.js +2 -0
- package/dist/src/debugger/debugger.service.js.map +1 -1
- package/dist/src/domain/node-health.js +1 -1
- package/dist/src/domain/node-health.js.map +1 -1
- package/dist/src/domain/node.types.d.ts +2 -0
- package/dist/src/grpc/daml-lf-archive.d.ts +2 -0
- package/dist/src/grpc/daml-lf-archive.js +104 -0
- package/dist/src/grpc/daml-lf-archive.js.map +1 -0
- package/dist/src/grpc/grpc-operations.service.d.ts +1 -0
- package/dist/src/grpc/grpc-operations.service.js +10 -6
- package/dist/src/grpc/grpc-operations.service.js.map +1 -1
- package/dist/src/pqs/pqs-summary.service.d.ts +19 -1
- package/dist/src/pqs/pqs-summary.service.js +430 -61
- package/dist/src/pqs/pqs-summary.service.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +9 -6
- package/scripts/build-debug-dar.mjs +277 -0
- package/scripts/generate-daml-source-map.mjs +1512 -0
- package/scripts/prepare-debug-dars-from-workspace.mjs +181 -0
- package/dist/public/assets/DebuggerView-GIrRlNTJ.js +0 -2
- package/dist/public/assets/editor-C5uazxST.css +0 -1
- package/dist/public/assets/editor.api-8w-mShFJ.js +0 -820
- package/dist/public/assets/index-CdWdP2w6.js +0 -1
- package/dist/public/assets/index-fkZAWLbW.css +0 -1
|
@@ -28,6 +28,12 @@ const CANTON_COIN_TOKEN_ID = 'canton-coin';
|
|
|
28
28
|
const CANTON_COIN_TOKEN_NAME = 'Canton Coin';
|
|
29
29
|
const CANTON_COIN_TRANSFER_TEMPLATE_ID = 'Splice.AmuletTransferInstruction:AmuletTransferInstruction';
|
|
30
30
|
const CANTON_COIN_AMULET_TEMPLATE_ID = 'Splice.Amulet:Amulet';
|
|
31
|
+
const AMULET_RULES_TEMPLATE_ID = 'Splice.AmuletRules:AmuletRules';
|
|
32
|
+
const NATIVE_AMULET_SUPPORT_TEMPLATE_IDS = [
|
|
33
|
+
CANTON_COIN_AMULET_TEMPLATE_ID,
|
|
34
|
+
AMULET_RULES_TEMPLATE_ID,
|
|
35
|
+
'Splice.Amulet:ValidatorRight',
|
|
36
|
+
];
|
|
31
37
|
const NATIVE_AMULET_INTRINSIC_ID = 'Amulet';
|
|
32
38
|
const CIP56_HOLDING_TEMPLATE_ID = 'Splice.Api.Token.HoldingV1:Holding';
|
|
33
39
|
const CIP56_TRANSFER_TEMPLATE_ID = 'Splice.Api.Token.TransferInstructionV1:Transfer';
|
|
@@ -856,13 +862,14 @@ function singleUpdateQuery(node, eventOffset) {
|
|
|
856
862
|
limit 1
|
|
857
863
|
`;
|
|
858
864
|
}
|
|
859
|
-
function
|
|
865
|
+
function updateEventsByUpdateIdsQuery(node, updateIds) {
|
|
860
866
|
const relations = pqsCoreRelations(node);
|
|
861
|
-
const
|
|
867
|
+
const quotedIds = updateIds.map((updateId) => `'${escapeSqlLiteral(updateId)}'`).join(', ');
|
|
862
868
|
const contractTemplateId = contractTemplateIdentifierExpression('contract_tpe_row');
|
|
863
869
|
const exerciseTemplateId = contractTemplateIdentifierExpression('exercise_contract_tpe_row');
|
|
864
870
|
return `
|
|
865
871
|
select
|
|
872
|
+
update_id,
|
|
866
873
|
event_kind,
|
|
867
874
|
event_id,
|
|
868
875
|
contract_id,
|
|
@@ -876,6 +883,7 @@ function updateEventsQuery(node, updateId) {
|
|
|
876
883
|
raw
|
|
877
884
|
from (
|
|
878
885
|
select
|
|
886
|
+
tx.transaction_id::text as update_id,
|
|
879
887
|
'create'::text as event_kind,
|
|
880
888
|
event_row.event_id::text as event_id,
|
|
881
889
|
contract_row.contract_id::text as contract_id,
|
|
@@ -903,11 +911,12 @@ function updateEventsQuery(node, updateId) {
|
|
|
903
911
|
on contract_tpe_row.pk = contract_row.tpe_pk
|
|
904
912
|
left join ${relations.packages} package_row
|
|
905
913
|
on package_row.pk = contract_row.package_pk
|
|
906
|
-
where tx.transaction_id
|
|
914
|
+
where tx.transaction_id in (${quotedIds})
|
|
907
915
|
|
|
908
916
|
union all
|
|
909
917
|
|
|
910
918
|
select
|
|
919
|
+
tx.transaction_id::text as update_id,
|
|
911
920
|
case
|
|
912
921
|
when exercise_tpe_row.consuming then 'consuming_exercise'::text
|
|
913
922
|
else 'non_consuming_exercise'::text
|
|
@@ -941,11 +950,14 @@ function updateEventsQuery(node, updateId) {
|
|
|
941
950
|
on exercise_tpe_row.pk = exercise_row.tpe_pk
|
|
942
951
|
left join ${relations.packages} package_row
|
|
943
952
|
on package_row.pk = exercise_row.package_pk
|
|
944
|
-
where tx.transaction_id
|
|
953
|
+
where tx.transaction_id in (${quotedIds})
|
|
945
954
|
) update_events
|
|
946
|
-
order by event_id asc nulls last, event_kind asc, contract_id asc, template_id asc
|
|
955
|
+
order by update_id asc nulls last, event_id asc nulls last, event_kind asc, contract_id asc, template_id asc
|
|
947
956
|
`;
|
|
948
957
|
}
|
|
958
|
+
function updateEventsQuery(node, updateId) {
|
|
959
|
+
return updateEventsByUpdateIdsQuery(node, [updateId]);
|
|
960
|
+
}
|
|
949
961
|
function rewardCouponInstanceQuery(node, updateId) {
|
|
950
962
|
const relations = pqsCoreRelations(node);
|
|
951
963
|
const quotedId = `'${escapeSqlLiteral(normalizeByteaHex(updateId))}'`;
|
|
@@ -971,9 +983,11 @@ function rewardCouponInstanceQuery(node, updateId) {
|
|
|
971
983
|
limit 1
|
|
972
984
|
`;
|
|
973
985
|
}
|
|
974
|
-
function
|
|
986
|
+
function contractDetailsQuery(node, contractIds) {
|
|
975
987
|
const relations = pqsCoreRelations(node);
|
|
976
|
-
const
|
|
988
|
+
const quotedIds = contractIds
|
|
989
|
+
.map((contractId) => `'${escapeSqlLiteral(normalizeByteaHex(contractId))}'`)
|
|
990
|
+
.join(', ');
|
|
977
991
|
const contractTemplateId = contractTemplateIdentifierExpression('contract_tpe_row');
|
|
978
992
|
return `
|
|
979
993
|
with selected_contract as (
|
|
@@ -989,8 +1003,7 @@ function contractDetailQuery(node, contractId) {
|
|
|
989
1003
|
on contract_tpe_row.pk = contract_row.tpe_pk
|
|
990
1004
|
left join ${relations.packages} package_row
|
|
991
1005
|
on package_row.pk = contract_row.package_pk
|
|
992
|
-
where contract_row.contract_id
|
|
993
|
-
limit 1
|
|
1006
|
+
where contract_row.contract_id in (${quotedIds})
|
|
994
1007
|
)
|
|
995
1008
|
select
|
|
996
1009
|
contract_row.contract_id,
|
|
@@ -1010,6 +1023,9 @@ function contractDetailQuery(node, contractId) {
|
|
|
1010
1023
|
on archived_tx.ix = contract_row.archived_at_ix
|
|
1011
1024
|
`;
|
|
1012
1025
|
}
|
|
1026
|
+
function contractDetailQuery(node, contractId) {
|
|
1027
|
+
return contractDetailsQuery(node, [contractId]);
|
|
1028
|
+
}
|
|
1013
1029
|
function tokenRowsQuery(node, limit, templateIds, templatePatterns = []) {
|
|
1014
1030
|
const relations = pqsCoreRelations(node);
|
|
1015
1031
|
const normalizedLimit = Number.isFinite(limit) && Number(limit) > 0 ? Math.trunc(limit) : TOKEN_TRANSFER_CACHE_LIMIT;
|
|
@@ -1055,6 +1071,21 @@ function tokenRowsQuery(node, limit, templateIds, templatePatterns = []) {
|
|
|
1055
1071
|
limit ${normalizedLimit}
|
|
1056
1072
|
`;
|
|
1057
1073
|
}
|
|
1074
|
+
function nativeAmuletSupportQuery(node) {
|
|
1075
|
+
const relations = pqsCoreRelations(node);
|
|
1076
|
+
const templateIds = NATIVE_AMULET_SUPPORT_TEMPLATE_IDS
|
|
1077
|
+
.map((templateId) => `'${escapeSqlLiteral(templateId)}'`)
|
|
1078
|
+
.join(',\n ');
|
|
1079
|
+
const templateId = contractTemplateIdentifierExpression('contract_tpe_row');
|
|
1080
|
+
return `
|
|
1081
|
+
select ${templateId} as template_id
|
|
1082
|
+
from ${relations.contractTpe} contract_tpe_row
|
|
1083
|
+
where ${templateId} in (
|
|
1084
|
+
${templateIds}
|
|
1085
|
+
)
|
|
1086
|
+
limit 1
|
|
1087
|
+
`;
|
|
1088
|
+
}
|
|
1058
1089
|
function recentCip112MovementUpdateIdsQuery(node, limit) {
|
|
1059
1090
|
const relations = pqsCoreRelations(node);
|
|
1060
1091
|
const normalizedLimit = Number.isFinite(limit) && Number(limit) > 0 ? Math.trunc(limit) : TOKEN_TRANSFER_CACHE_LIMIT;
|
|
@@ -1284,7 +1315,7 @@ let PqsSummaryService = class PqsSummaryService {
|
|
|
1284
1315
|
if (nodesToFetch.length === 0) {
|
|
1285
1316
|
break;
|
|
1286
1317
|
}
|
|
1287
|
-
const
|
|
1318
|
+
const settled = await Promise.allSettled(nodesToFetch.map((state) => this.fetchRecentUpdates(state.node, {
|
|
1288
1319
|
limit: pageSize,
|
|
1289
1320
|
parties,
|
|
1290
1321
|
templates,
|
|
@@ -1292,8 +1323,25 @@ let PqsSummaryService = class PqsSummaryService {
|
|
|
1292
1323
|
hideSplice,
|
|
1293
1324
|
before: state.nextBefore,
|
|
1294
1325
|
})));
|
|
1295
|
-
|
|
1326
|
+
const successfulResponses = [];
|
|
1327
|
+
settled.forEach((result, index) => {
|
|
1296
1328
|
const state = nodesToFetch[index];
|
|
1329
|
+
if (!state) {
|
|
1330
|
+
return;
|
|
1331
|
+
}
|
|
1332
|
+
if (result.status !== 'fulfilled') {
|
|
1333
|
+
state.exhausted = true;
|
|
1334
|
+
return;
|
|
1335
|
+
}
|
|
1336
|
+
successfulResponses.push({
|
|
1337
|
+
state,
|
|
1338
|
+
response: result.value,
|
|
1339
|
+
});
|
|
1340
|
+
});
|
|
1341
|
+
if (successfulResponses.length === 0) {
|
|
1342
|
+
throw settled.find((result) => result.status === 'rejected')?.reason;
|
|
1343
|
+
}
|
|
1344
|
+
successfulResponses.forEach(({ response, state }) => {
|
|
1297
1345
|
for (const update of response.updates) {
|
|
1298
1346
|
mergedUpdatesByKey.set(`${state.node.id}:${update.eventOffset}:${update.updateId}`, {
|
|
1299
1347
|
nodeId: state.node.id,
|
|
@@ -1717,29 +1765,52 @@ let PqsSummaryService = class PqsSummaryService {
|
|
|
1717
1765
|
}
|
|
1718
1766
|
async fetchActiveParties(nodes) {
|
|
1719
1767
|
return {
|
|
1720
|
-
nodes: await Promise.all(nodes.map(async (node) => (
|
|
1768
|
+
nodes: await Promise.all(nodes.map(async (node) => this.buildActivePartiesEntry(node))),
|
|
1769
|
+
};
|
|
1770
|
+
}
|
|
1771
|
+
async buildActivePartiesEntry(node) {
|
|
1772
|
+
try {
|
|
1773
|
+
return {
|
|
1721
1774
|
nodeId: node.id,
|
|
1722
1775
|
label: node.label,
|
|
1723
1776
|
mode: node.mode,
|
|
1724
1777
|
parties: await this.fetchActivePartiesForNode(node),
|
|
1725
|
-
|
|
1726
|
-
|
|
1778
|
+
activePartiesStatus: 'ok',
|
|
1779
|
+
activePartiesError: null,
|
|
1780
|
+
};
|
|
1781
|
+
}
|
|
1782
|
+
catch (error) {
|
|
1783
|
+
return {
|
|
1784
|
+
nodeId: node.id,
|
|
1785
|
+
label: node.label,
|
|
1786
|
+
mode: node.mode,
|
|
1787
|
+
parties: [],
|
|
1788
|
+
activePartiesStatus: 'pqs_error',
|
|
1789
|
+
activePartiesError: error instanceof Error ? error.message : 'Unknown error',
|
|
1790
|
+
};
|
|
1791
|
+
}
|
|
1727
1792
|
}
|
|
1728
1793
|
async fetchPartyDetail(nodes, partyId) {
|
|
1729
1794
|
const normalizedPartyId = this.normalizePartyIdentifier(partyId);
|
|
1730
1795
|
const grpcOperationsService = this.grpcOperationsService;
|
|
1731
|
-
const activePartiesByNode = await Promise.
|
|
1796
|
+
const activePartiesByNode = (await Promise.allSettled(nodes.map(async (node) => ({
|
|
1732
1797
|
node,
|
|
1733
1798
|
parties: await this.fetchActivePartiesForNode(node),
|
|
1734
|
-
})))
|
|
1735
|
-
|
|
1799
|
+
}))))
|
|
1800
|
+
.filter((result) => result.status === 'fulfilled')
|
|
1801
|
+
.map((result) => result.value);
|
|
1802
|
+
const recentUpdatesByNode = (await Promise.allSettled(nodes.map(async (node) => ({
|
|
1736
1803
|
node,
|
|
1737
1804
|
updates: await this.fetchPartyRecentUpdatesForNode(node, normalizedPartyId, 10),
|
|
1738
|
-
})))
|
|
1739
|
-
|
|
1805
|
+
}))))
|
|
1806
|
+
.filter((result) => result.status === 'fulfilled')
|
|
1807
|
+
.map((result) => result.value);
|
|
1808
|
+
const recentContractsByNode = (await Promise.allSettled(nodes.map(async (node) => ({
|
|
1740
1809
|
node,
|
|
1741
1810
|
contracts: await this.fetchPartyRecentContractsForNode(node, normalizedPartyId, 10),
|
|
1742
|
-
})))
|
|
1811
|
+
}))))
|
|
1812
|
+
.filter((result) => result.status === 'fulfilled')
|
|
1813
|
+
.map((result) => result.value);
|
|
1743
1814
|
const localPartiesByNode = grpcOperationsService
|
|
1744
1815
|
? await Promise.all(nodes.map(async (node) => {
|
|
1745
1816
|
try {
|
|
@@ -1847,10 +1918,12 @@ let PqsSummaryService = class PqsSummaryService {
|
|
|
1847
1918
|
async fetchNamespaceDetail(nodes, namespaceId) {
|
|
1848
1919
|
const normalizedNamespaceId = namespaceId.trim();
|
|
1849
1920
|
const grpcOperationsService = this.grpcOperationsService;
|
|
1850
|
-
const activePartiesByNode = await Promise.
|
|
1921
|
+
const activePartiesByNode = (await Promise.allSettled(nodes.map(async (node) => ({
|
|
1851
1922
|
node,
|
|
1852
1923
|
parties: (await this.fetchActivePartiesForNode(node)).filter((partyId) => this.extractNamespaceIdentifier(partyId) === normalizedNamespaceId),
|
|
1853
|
-
})))
|
|
1924
|
+
}))))
|
|
1925
|
+
.filter((result) => result.status === 'fulfilled')
|
|
1926
|
+
.map((result) => result.value);
|
|
1854
1927
|
const localPartiesByNode = grpcOperationsService
|
|
1855
1928
|
? await Promise.all(nodes.map(async (node) => {
|
|
1856
1929
|
try {
|
|
@@ -1943,7 +2016,9 @@ let PqsSummaryService = class PqsSummaryService {
|
|
|
1943
2016
|
async fetchNamespaceParties(nodes, namespaceId, options) {
|
|
1944
2017
|
const normalizedNamespaceId = namespaceId.trim();
|
|
1945
2018
|
const matchingParties = new Set();
|
|
1946
|
-
const activePartiesByNode = await Promise.
|
|
2019
|
+
const activePartiesByNode = (await Promise.allSettled(nodes.map(async (node) => (await this.fetchActivePartiesForNode(node)).filter((partyId) => this.extractNamespaceIdentifier(partyId) === normalizedNamespaceId))))
|
|
2020
|
+
.filter((result) => result.status === 'fulfilled')
|
|
2021
|
+
.map((result) => result.value);
|
|
1947
2022
|
for (const parties of activePartiesByNode) {
|
|
1948
2023
|
for (const partyId of parties) {
|
|
1949
2024
|
matchingParties.add(partyId);
|
|
@@ -2039,7 +2114,7 @@ let PqsSummaryService = class PqsSummaryService {
|
|
|
2039
2114
|
if (nodesToFetch.length === 0) {
|
|
2040
2115
|
break;
|
|
2041
2116
|
}
|
|
2042
|
-
const
|
|
2117
|
+
const settled = await Promise.allSettled(nodesToFetch.map((state) => this.fetchNodeContracts(state.node, {
|
|
2043
2118
|
limit: pageSize,
|
|
2044
2119
|
before: state.nextBefore,
|
|
2045
2120
|
parties: activePartyFilters.length > 0 ? activePartyFilters : undefined,
|
|
@@ -2047,8 +2122,25 @@ let PqsSummaryService = class PqsSummaryService {
|
|
|
2047
2122
|
partyMode,
|
|
2048
2123
|
hideSplice,
|
|
2049
2124
|
})));
|
|
2050
|
-
|
|
2125
|
+
const successfulResponses = [];
|
|
2126
|
+
settled.forEach((result, index) => {
|
|
2051
2127
|
const state = nodesToFetch[index];
|
|
2128
|
+
if (!state) {
|
|
2129
|
+
return;
|
|
2130
|
+
}
|
|
2131
|
+
if (result.status !== 'fulfilled') {
|
|
2132
|
+
state.exhausted = true;
|
|
2133
|
+
return;
|
|
2134
|
+
}
|
|
2135
|
+
successfulResponses.push({
|
|
2136
|
+
state,
|
|
2137
|
+
response: result.value,
|
|
2138
|
+
});
|
|
2139
|
+
});
|
|
2140
|
+
if (successfulResponses.length === 0) {
|
|
2141
|
+
throw settled.find((result) => result.status === 'rejected')?.reason;
|
|
2142
|
+
}
|
|
2143
|
+
successfulResponses.forEach(({ response, state }) => {
|
|
2052
2144
|
for (const contract of response.contracts) {
|
|
2053
2145
|
mergedContractsByKey.set(`${state.node.id}:${contract.contractId}`, {
|
|
2054
2146
|
nodeId: state.node.id,
|
|
@@ -2129,12 +2221,29 @@ let PqsSummaryService = class PqsSummaryService {
|
|
|
2129
2221
|
if (nodesToFetch.length === 0) {
|
|
2130
2222
|
break;
|
|
2131
2223
|
}
|
|
2132
|
-
const
|
|
2224
|
+
const settled = await Promise.allSettled(nodesToFetch.map((state) => this.fetchPartyContractsForNode(state.node, normalizedPartyId, {
|
|
2133
2225
|
limit: pageSize,
|
|
2134
2226
|
before: state.nextBefore,
|
|
2135
2227
|
})));
|
|
2136
|
-
|
|
2228
|
+
const successfulResponses = [];
|
|
2229
|
+
settled.forEach((result, index) => {
|
|
2137
2230
|
const state = nodesToFetch[index];
|
|
2231
|
+
if (!state) {
|
|
2232
|
+
return;
|
|
2233
|
+
}
|
|
2234
|
+
if (result.status !== 'fulfilled') {
|
|
2235
|
+
state.exhausted = true;
|
|
2236
|
+
return;
|
|
2237
|
+
}
|
|
2238
|
+
successfulResponses.push({
|
|
2239
|
+
state,
|
|
2240
|
+
response: result.value,
|
|
2241
|
+
});
|
|
2242
|
+
});
|
|
2243
|
+
if (successfulResponses.length === 0) {
|
|
2244
|
+
throw settled.find((result) => result.status === 'rejected')?.reason;
|
|
2245
|
+
}
|
|
2246
|
+
successfulResponses.forEach(({ response, state }) => {
|
|
2138
2247
|
for (const contract of response.contracts) {
|
|
2139
2248
|
mergedContractsByKey.set(`${contract.nodeId}:${contract.contractId}`, contract);
|
|
2140
2249
|
}
|
|
@@ -2190,18 +2299,18 @@ let PqsSummaryService = class PqsSummaryService {
|
|
|
2190
2299
|
return this.paginateTokens(filteredTokens.sort(compareGlobalTokens), limit, options);
|
|
2191
2300
|
}
|
|
2192
2301
|
async fetchLatestTokenTransfers(nodes, limit = 25, options) {
|
|
2193
|
-
const mergedTransfers = this.
|
|
2302
|
+
const mergedTransfers = this.filterTokenTransfers(await this.loadMergedTokenTransfers(nodes), options);
|
|
2194
2303
|
return this.paginateTokenTransfers(mergedTransfers, limit, options);
|
|
2195
2304
|
}
|
|
2196
2305
|
async fetchTokenTransfers(nodes, tokenId, limit = 25, options) {
|
|
2197
2306
|
const normalizedTokenId = this.normalizeTokenId(tokenId);
|
|
2198
2307
|
await this.findObservedToken(nodes, normalizedTokenId);
|
|
2199
|
-
const mergedTransfers = this.
|
|
2308
|
+
const mergedTransfers = this.filterTokenTransfers(await this.loadMergedTokenTransfers(nodes), options);
|
|
2200
2309
|
const directTransfers = mergedTransfers.filter((transfer) => transfer.tokenId === normalizedTokenId);
|
|
2201
2310
|
if (directTransfers.length > 0) {
|
|
2202
2311
|
return this.paginateTokenTransfers(directTransfers, limit, options);
|
|
2203
2312
|
}
|
|
2204
|
-
const recoveredTransfers = this.
|
|
2313
|
+
const recoveredTransfers = this.filterTokenTransfers(await this.recoverTokenTransfersFromActiveHolders(nodes, normalizedTokenId), options);
|
|
2205
2314
|
return this.paginateTokenTransfers(recoveredTransfers, limit, options);
|
|
2206
2315
|
}
|
|
2207
2316
|
async fetchTokenTransferDetail(nodes, transferId) {
|
|
@@ -2341,10 +2450,11 @@ let PqsSummaryService = class PqsSummaryService {
|
|
|
2341
2450
|
node,
|
|
2342
2451
|
transfers: await this.loadCachedTokenTransfers(node),
|
|
2343
2452
|
})));
|
|
2344
|
-
const
|
|
2453
|
+
const successfulRefreshes = refreshResults.filter((result) => result.status === 'fulfilled');
|
|
2454
|
+
const successfulTransfers = successfulRefreshes
|
|
2345
2455
|
.filter((result) => result.status === 'fulfilled')
|
|
2346
2456
|
.flatMap((result) => result.value.transfers);
|
|
2347
|
-
if (
|
|
2457
|
+
if (successfulRefreshes.length === 0) {
|
|
2348
2458
|
const firstFailure = refreshResults.find((result) => result.status === 'rejected');
|
|
2349
2459
|
if (firstFailure) {
|
|
2350
2460
|
throw firstFailure.reason;
|
|
@@ -2364,9 +2474,9 @@ let PqsSummaryService = class PqsSummaryService {
|
|
|
2364
2474
|
.filter((holder) => holder.tokenId === tokenId && holder.contractId !== null);
|
|
2365
2475
|
const recoveredTransfers = [];
|
|
2366
2476
|
const seenContracts = new Set();
|
|
2477
|
+
const contractIdsByNode = new Map();
|
|
2367
2478
|
for (const holder of candidateHolders) {
|
|
2368
|
-
|
|
2369
|
-
if (!node || !holder.contractId) {
|
|
2479
|
+
if (!nodeById.has(holder.nodeId) || !holder.contractId) {
|
|
2370
2480
|
continue;
|
|
2371
2481
|
}
|
|
2372
2482
|
const dedupeKey = `${holder.nodeId}\u0000${holder.contractId}`;
|
|
@@ -2374,19 +2484,38 @@ let PqsSummaryService = class PqsSummaryService {
|
|
|
2374
2484
|
continue;
|
|
2375
2485
|
}
|
|
2376
2486
|
seenContracts.add(dedupeKey);
|
|
2377
|
-
const
|
|
2378
|
-
|
|
2379
|
-
|
|
2380
|
-
|
|
2487
|
+
const nodeContractIds = contractIdsByNode.get(holder.nodeId);
|
|
2488
|
+
if (nodeContractIds) {
|
|
2489
|
+
nodeContractIds.push(holder.contractId);
|
|
2490
|
+
}
|
|
2491
|
+
else {
|
|
2492
|
+
contractIdsByNode.set(holder.nodeId, [holder.contractId]);
|
|
2493
|
+
}
|
|
2494
|
+
}
|
|
2495
|
+
for (const [nodeId, contractIds] of contractIdsByNode) {
|
|
2496
|
+
const node = nodeById.get(nodeId);
|
|
2497
|
+
if (!node) {
|
|
2381
2498
|
continue;
|
|
2382
2499
|
}
|
|
2383
|
-
const
|
|
2384
|
-
const
|
|
2385
|
-
|
|
2386
|
-
|
|
2387
|
-
|
|
2388
|
-
|
|
2389
|
-
|
|
2500
|
+
const client = this.clientFactory.getClient(node);
|
|
2501
|
+
const contractRows = await this.fetchContractDetailsByIds(node, client.query.bind(client), contractIds);
|
|
2502
|
+
const eventsByUpdateId = await this.fetchEventsByUpdateIds(node, client.query.bind(client), contractRows
|
|
2503
|
+
.map((contractRow) => contractRow.created_update_id)
|
|
2504
|
+
.filter((updateId) => typeof updateId === 'string'));
|
|
2505
|
+
for (const contractRow of contractRows) {
|
|
2506
|
+
if (typeof contractRow.created_update_id !== 'string') {
|
|
2507
|
+
continue;
|
|
2508
|
+
}
|
|
2509
|
+
const events = eventsByUpdateId.get(contractRow.created_update_id) ?? [];
|
|
2510
|
+
const inferredTransfers = this.extractCip112TokenMovements(node, {
|
|
2511
|
+
update_id: contractRow.created_update_id,
|
|
2512
|
+
event_offset: contractRow.created_event_offset,
|
|
2513
|
+
record_time: contractRow.created_record_time,
|
|
2514
|
+
}, events, {
|
|
2515
|
+
canonicalShareTokenId: tokenId,
|
|
2516
|
+
}).filter((transfer) => transfer.tokenId === tokenId);
|
|
2517
|
+
recoveredTransfers.push(...inferredTransfers);
|
|
2518
|
+
}
|
|
2390
2519
|
}
|
|
2391
2520
|
return this.mergeTokenTransfers(recoveredTransfers);
|
|
2392
2521
|
}
|
|
@@ -2425,13 +2554,15 @@ let PqsSummaryService = class PqsSummaryService {
|
|
|
2425
2554
|
transfers: pagedTransfers,
|
|
2426
2555
|
};
|
|
2427
2556
|
}
|
|
2428
|
-
|
|
2557
|
+
filterTokenTransfers(transfers, options) {
|
|
2429
2558
|
const activeFromParties = normalizePartyFilters(options?.fromParties);
|
|
2430
2559
|
const activeToParties = normalizePartyFilters(options?.toParties);
|
|
2560
|
+
const activeMovementTypes = this.normalizeTokenTransferMovementTypeFilters(options?.movementTypes);
|
|
2431
2561
|
const amountGt = options?.amountGt?.trim() || null;
|
|
2432
2562
|
const amountLt = options?.amountLt?.trim() || null;
|
|
2433
2563
|
if (activeFromParties.length === 0 &&
|
|
2434
2564
|
activeToParties.length === 0 &&
|
|
2565
|
+
activeMovementTypes.length === 0 &&
|
|
2435
2566
|
amountGt === null &&
|
|
2436
2567
|
amountLt === null) {
|
|
2437
2568
|
return transfers;
|
|
@@ -2441,11 +2572,13 @@ let PqsSummaryService = class PqsSummaryService {
|
|
|
2441
2572
|
(transfer.sender !== null && activeFromParties.includes(transfer.sender));
|
|
2442
2573
|
const matchesTo = activeToParties.length === 0 ||
|
|
2443
2574
|
(transfer.receiver !== null && activeToParties.includes(transfer.receiver));
|
|
2575
|
+
const matchesMovementType = activeMovementTypes.length === 0 ||
|
|
2576
|
+
activeMovementTypes.includes(this.effectiveTokenTransferMovementType(transfer).toLowerCase());
|
|
2444
2577
|
const matchesAmountGt = amountGt === null ||
|
|
2445
2578
|
(transfer.amount !== null && this.compareNumericStrings(transfer.amount, amountGt) > 0);
|
|
2446
2579
|
const matchesAmountLt = amountLt === null ||
|
|
2447
2580
|
(transfer.amount !== null && this.compareNumericStrings(transfer.amount, amountLt) < 0);
|
|
2448
|
-
return matchesFrom && matchesTo && matchesAmountGt && matchesAmountLt;
|
|
2581
|
+
return matchesFrom && matchesTo && matchesMovementType && matchesAmountGt && matchesAmountLt;
|
|
2449
2582
|
});
|
|
2450
2583
|
}
|
|
2451
2584
|
async fetchUpdateDetail(node, eventOffset) {
|
|
@@ -2606,16 +2739,15 @@ let PqsSummaryService = class PqsSummaryService {
|
|
|
2606
2739
|
return cached.tokens;
|
|
2607
2740
|
}
|
|
2608
2741
|
const useGrpcHoldingViews = node.mode === 'pqs_with_grpc' && this.grpcOperationsService !== undefined;
|
|
2609
|
-
const [pqsTokens, grpcTokens] = await Promise.all([
|
|
2610
|
-
this.fetchObservedTokensForNode(node, TOKEN_TRANSFER_CACHE_LIMIT,
|
|
2611
|
-
includeCip112: !useGrpcHoldingViews,
|
|
2612
|
-
}),
|
|
2742
|
+
const [pqsTokens, grpcTokens, builtinTokens] = await Promise.all([
|
|
2743
|
+
this.fetchObservedTokensForNode(node, TOKEN_TRANSFER_CACHE_LIMIT),
|
|
2613
2744
|
useGrpcHoldingViews
|
|
2614
2745
|
? this.grpcOperationsService.fetchHoldingV2Tokens(node)
|
|
2615
2746
|
: Promise.resolve([]),
|
|
2747
|
+
this.fetchBuiltinTokensForNode(node),
|
|
2616
2748
|
]);
|
|
2617
2749
|
const dedupedTokens = new Map();
|
|
2618
|
-
for (const token of [...pqsTokens, ...grpcTokens]) {
|
|
2750
|
+
for (const token of [...pqsTokens, ...grpcTokens, ...builtinTokens]) {
|
|
2619
2751
|
if (!dedupedTokens.has(token.tokenId)) {
|
|
2620
2752
|
dedupedTokens.set(token.tokenId, token);
|
|
2621
2753
|
}
|
|
@@ -2627,6 +2759,31 @@ let PqsSummaryService = class PqsSummaryService {
|
|
|
2627
2759
|
});
|
|
2628
2760
|
return tokens;
|
|
2629
2761
|
}
|
|
2762
|
+
async fetchBuiltinTokensForNode(node) {
|
|
2763
|
+
const client = this.clientFactory.getClient(node);
|
|
2764
|
+
const result = await client.query(nativeAmuletSupportQuery(node));
|
|
2765
|
+
const rows = Array.isArray(result.rows) ? result.rows : [];
|
|
2766
|
+
const hasNativeAmuletSupport = rows.some((row) => {
|
|
2767
|
+
if (!row || typeof row !== 'object') {
|
|
2768
|
+
return false;
|
|
2769
|
+
}
|
|
2770
|
+
const templateId = row.template_id;
|
|
2771
|
+
return (typeof templateId === 'string' &&
|
|
2772
|
+
NATIVE_AMULET_SUPPORT_TEMPLATE_IDS.includes(this.normalizeTemplateIdentifier(templateId)));
|
|
2773
|
+
});
|
|
2774
|
+
if (!hasNativeAmuletSupport) {
|
|
2775
|
+
return [];
|
|
2776
|
+
}
|
|
2777
|
+
return [
|
|
2778
|
+
{
|
|
2779
|
+
tokenId: CANTON_COIN_TOKEN_ID,
|
|
2780
|
+
name: CANTON_COIN_TOKEN_NAME,
|
|
2781
|
+
symbol: null,
|
|
2782
|
+
issuer: null,
|
|
2783
|
+
source: 'pqs',
|
|
2784
|
+
},
|
|
2785
|
+
];
|
|
2786
|
+
}
|
|
2630
2787
|
async fetchObservedTokensForNode(node, limit, options) {
|
|
2631
2788
|
const client = this.clientFactory.getClient(node);
|
|
2632
2789
|
const includeCip112 = options?.includeCip112 ?? true;
|
|
@@ -2812,17 +2969,93 @@ let PqsSummaryService = class PqsSummaryService {
|
|
|
2812
2969
|
const result = await client.query(recentCip112MovementUpdateIdsQuery(node, limit));
|
|
2813
2970
|
const rows = result.rows ?? [];
|
|
2814
2971
|
const transfers = [];
|
|
2972
|
+
const rawUpdateIds = rows
|
|
2973
|
+
.map((row) => (typeof row.update_id === 'string' ? row.update_id : null))
|
|
2974
|
+
.filter((updateId) => Boolean(updateId && this.isHexTokenMovementUpdateId(updateId)));
|
|
2975
|
+
const eventsByUpdateId = await this.fetchEventsByUpdateIds(node, client.query.bind(client), rawUpdateIds);
|
|
2815
2976
|
for (const row of rows) {
|
|
2816
2977
|
const rawUpdateId = typeof row.update_id === 'string' ? row.update_id : null;
|
|
2817
2978
|
if (!rawUpdateId || !this.isHexTokenMovementUpdateId(rawUpdateId)) {
|
|
2818
2979
|
continue;
|
|
2819
2980
|
}
|
|
2820
|
-
const events =
|
|
2821
|
-
transfers.push(...this.
|
|
2981
|
+
const events = eventsByUpdateId.get(rawUpdateId) ?? [];
|
|
2982
|
+
transfers.push(...this.extractCip112TokenMovements(node, row, events));
|
|
2983
|
+
}
|
|
2984
|
+
return transfers;
|
|
2985
|
+
}
|
|
2986
|
+
extractCip112TokenMovements(node, update, events, options) {
|
|
2987
|
+
const standardTransfers = this.extractStandardCip112TokenMovements(node, update, events, options);
|
|
2988
|
+
if (standardTransfers.length > 0) {
|
|
2989
|
+
return standardTransfers;
|
|
2990
|
+
}
|
|
2991
|
+
return this.inferCip112TokenMovements(node, update, events, options);
|
|
2992
|
+
}
|
|
2993
|
+
extractStandardCip112TokenMovements(node, update, events, options) {
|
|
2994
|
+
const createTokensById = new Map();
|
|
2995
|
+
for (const event of events) {
|
|
2996
|
+
if (event.eventKind !== 'create' ||
|
|
2997
|
+
!this.isCip112TemplateId(event.templateId) ||
|
|
2998
|
+
event.createData?.status !== 'decoded') {
|
|
2999
|
+
continue;
|
|
3000
|
+
}
|
|
3001
|
+
const token = this.extractObservedTokenSummary(event.templateId, event.createData);
|
|
3002
|
+
if (token) {
|
|
3003
|
+
createTokensById.set(token.tokenId, token);
|
|
3004
|
+
}
|
|
3005
|
+
}
|
|
3006
|
+
const transfers = [];
|
|
3007
|
+
const eventLogExercises = events.filter((event) => event.eventKind === 'non_consuming_exercise' &&
|
|
3008
|
+
(event.choice === 'HoldingsChange' || event.choice === 'EventLog_HoldingsChange') &&
|
|
3009
|
+
event.exerciseData?.argument.status === 'decoded' &&
|
|
3010
|
+
this.isRecordValue(event.exerciseData.argument.value));
|
|
3011
|
+
for (const event of eventLogExercises) {
|
|
3012
|
+
const argument = event.exerciseData?.argument;
|
|
3013
|
+
if (!argument || argument.status !== 'decoded' || !this.isRecordValue(argument.value)) {
|
|
3014
|
+
continue;
|
|
3015
|
+
}
|
|
3016
|
+
const account = this.findRecordField(argument.value, 'account');
|
|
3017
|
+
const transferLegs = this.readListField(argument.value, 'transferLegSides');
|
|
3018
|
+
const admin = this.readScalarField(argument.value, 'admin');
|
|
3019
|
+
if (!account || !admin || transferLegs.length === 0) {
|
|
3020
|
+
continue;
|
|
3021
|
+
}
|
|
3022
|
+
for (const leg of transferLegs) {
|
|
3023
|
+
if (!this.isRecordValue(leg)) {
|
|
3024
|
+
continue;
|
|
3025
|
+
}
|
|
3026
|
+
const side = this.readConstructorField(leg, 'side');
|
|
3027
|
+
if (side !== 'SenderSide') {
|
|
3028
|
+
continue;
|
|
3029
|
+
}
|
|
3030
|
+
const transferLegId = this.readScalarField(leg, 'transferLegId');
|
|
3031
|
+
const amount = this.readScalarField(leg, 'amount');
|
|
3032
|
+
const instrumentId = this.readScalarField(leg, 'instrumentId');
|
|
3033
|
+
const otherSideAccount = this.findRecordField(leg, 'otherside');
|
|
3034
|
+
if (!transferLegId || !instrumentId || !otherSideAccount) {
|
|
3035
|
+
continue;
|
|
3036
|
+
}
|
|
3037
|
+
const token = this.resolveEventLogTokenSummary(admin, instrumentId, createTokensById, options?.canonicalShareTokenId ?? null);
|
|
3038
|
+
const movementType = this.classifyEventLogMovementType(account, otherSideAccount, admin, instrumentId);
|
|
3039
|
+
transfers.push({
|
|
3040
|
+
rowId: this.buildTokenTransferLegRowId(typeof update.update_id === 'string' ? this.normalizeUpdateId(update.update_id) : '', event.eventId, transferLegId, movementType),
|
|
3041
|
+
movementType,
|
|
3042
|
+
source: 'pqs',
|
|
3043
|
+
nodeId: node.id,
|
|
3044
|
+
label: node.label,
|
|
3045
|
+
tokenId: token.tokenId,
|
|
3046
|
+
tokenName: token.name,
|
|
3047
|
+
amount,
|
|
3048
|
+
sender: this.readAccountParty(account),
|
|
3049
|
+
receiver: this.readAccountParty(otherSideAccount),
|
|
3050
|
+
eventOffset: this.normalizeOptionalScalar(update.event_offset) ?? '',
|
|
3051
|
+
updateId: typeof update.update_id === 'string' ? this.normalizeUpdateId(update.update_id) : '',
|
|
3052
|
+
recordTime: typeof update.record_time === 'string' ? update.record_time : null,
|
|
3053
|
+
});
|
|
3054
|
+
}
|
|
2822
3055
|
}
|
|
2823
3056
|
return transfers;
|
|
2824
3057
|
}
|
|
2825
|
-
inferCip112TokenMovements(node, update, events) {
|
|
3058
|
+
inferCip112TokenMovements(node, update, events, options) {
|
|
2826
3059
|
const createEvents = events.filter((event) => event.eventKind === 'create' &&
|
|
2827
3060
|
this.isCip112TemplateId(event.templateId) &&
|
|
2828
3061
|
event.createData?.status === 'decoded' &&
|
|
@@ -2842,10 +3075,11 @@ let PqsSummaryService = class PqsSummaryService {
|
|
|
2842
3075
|
? this.readScalarField(event.createData.value, 'owner')
|
|
2843
3076
|
: null)
|
|
2844
3077
|
.find((owner) => Boolean(owner));
|
|
2845
|
-
|
|
3078
|
+
const shouldEmitCreateMovements = transferExercises.length > 0 || (transferExercises.length === 0 && mintExercises.length === 0);
|
|
3079
|
+
if (shouldEmitCreateMovements) {
|
|
2846
3080
|
for (const event of createEvents) {
|
|
2847
3081
|
const movementType = 'Create';
|
|
2848
|
-
const transfer = this.buildInferredCip112Movement(node, update, event, movementType, !this.isShareLikeCip112Template(event.templateId) ? shareOwnerFallback : null);
|
|
3082
|
+
const transfer = this.buildInferredCip112Movement(node, update, event, movementType, !this.isShareLikeCip112Template(event.templateId) ? shareOwnerFallback : null, options?.canonicalShareTokenId);
|
|
2849
3083
|
if (transfer) {
|
|
2850
3084
|
transfers.push(transfer);
|
|
2851
3085
|
}
|
|
@@ -2864,7 +3098,7 @@ let PqsSummaryService = class PqsSummaryService {
|
|
|
2864
3098
|
}
|
|
2865
3099
|
return transfers;
|
|
2866
3100
|
}
|
|
2867
|
-
buildInferredCip112Movement(node, update, event, movementType, receiverFallback = null) {
|
|
3101
|
+
buildInferredCip112Movement(node, update, event, movementType, receiverFallback = null, canonicalShareTokenId = null) {
|
|
2868
3102
|
if (event.createData?.status !== 'decoded') {
|
|
2869
3103
|
return null;
|
|
2870
3104
|
}
|
|
@@ -2876,13 +3110,16 @@ let PqsSummaryService = class PqsSummaryService {
|
|
|
2876
3110
|
if (!token) {
|
|
2877
3111
|
return null;
|
|
2878
3112
|
}
|
|
3113
|
+
const tokenId = canonicalShareTokenId && this.isShareLikeCip112Template(event.templateId)
|
|
3114
|
+
? canonicalShareTokenId
|
|
3115
|
+
: token.tokenId;
|
|
2879
3116
|
return {
|
|
2880
3117
|
rowId: this.buildTokenMovementRowId(typeof update.update_id === 'string' ? update.update_id : this.normalizeUpdateId(''), event.eventId, event.templateId, movementType),
|
|
2881
3118
|
movementType,
|
|
2882
3119
|
source: INFERRED_HOLDING_V2_SOURCE,
|
|
2883
3120
|
nodeId: node.id,
|
|
2884
3121
|
label: node.label,
|
|
2885
|
-
tokenId
|
|
3122
|
+
tokenId,
|
|
2886
3123
|
tokenName: token.name,
|
|
2887
3124
|
amount: this.readScalarField(record, 'amount'),
|
|
2888
3125
|
sender: movementType === 'Mint' ? this.readScalarField(record, 'issuer') : null,
|
|
@@ -2984,6 +3221,17 @@ let PqsSummaryService = class PqsSummaryService {
|
|
|
2984
3221
|
normalizeTokenId(tokenId) {
|
|
2985
3222
|
return tokenId.trim();
|
|
2986
3223
|
}
|
|
3224
|
+
normalizeTokenTransferMovementTypeFilters(movementTypes) {
|
|
3225
|
+
return Array.from(new Set((movementTypes ?? [])
|
|
3226
|
+
.map((movementType) => movementType.trim().toLowerCase())
|
|
3227
|
+
.filter((movementType) => movementType.length > 0)));
|
|
3228
|
+
}
|
|
3229
|
+
effectiveTokenTransferMovementType(transfer) {
|
|
3230
|
+
const normalizedMovementType = transfer.movementType?.trim();
|
|
3231
|
+
return normalizedMovementType && normalizedMovementType.length > 0
|
|
3232
|
+
? normalizedMovementType
|
|
3233
|
+
: 'Transfer';
|
|
3234
|
+
}
|
|
2987
3235
|
isCip112TemplateId(templateId) {
|
|
2988
3236
|
return typeof templateId === 'string' && templateId.includes('.CIP112:');
|
|
2989
3237
|
}
|
|
@@ -3001,6 +3249,33 @@ let PqsSummaryService = class PqsSummaryService {
|
|
|
3001
3249
|
buildTokenMovementRowId(updateId, eventId, templateId, movementType) {
|
|
3002
3250
|
return [updateId, eventId ?? '', templateId ?? '', movementType].join(':');
|
|
3003
3251
|
}
|
|
3252
|
+
buildTokenTransferLegRowId(updateId, eventId, transferLegId, movementType) {
|
|
3253
|
+
return [updateId, eventId ?? '', transferLegId, movementType].join(':');
|
|
3254
|
+
}
|
|
3255
|
+
resolveEventLogTokenSummary(admin, instrumentId, tokensById, canonicalShareTokenId) {
|
|
3256
|
+
const fallbackToken = this.buildObservedTokenSummary(instrumentId, admin, this.isNativeAmuletIntrinsicId(instrumentId) ? CANTON_COIN_TOKEN_NAME : instrumentId, null);
|
|
3257
|
+
const tokenId = canonicalShareTokenId && fallbackToken.tokenId === this.normalizeShareLikeIntrinsicTokenId(instrumentId)
|
|
3258
|
+
? canonicalShareTokenId
|
|
3259
|
+
: fallbackToken.tokenId;
|
|
3260
|
+
return tokensById.get(tokenId) ?? tokensById.get(fallbackToken.tokenId) ?? {
|
|
3261
|
+
...fallbackToken,
|
|
3262
|
+
tokenId,
|
|
3263
|
+
};
|
|
3264
|
+
}
|
|
3265
|
+
classifyEventLogMovementType(senderAccount, receiverAccount, admin, instrumentId) {
|
|
3266
|
+
if (this.isSyntheticEventLogAccount(senderAccount, admin, `${instrumentId}:mint`)) {
|
|
3267
|
+
return 'Mint';
|
|
3268
|
+
}
|
|
3269
|
+
if (this.isSyntheticEventLogAccount(receiverAccount, admin, `${instrumentId}:burn`)) {
|
|
3270
|
+
return 'Burn';
|
|
3271
|
+
}
|
|
3272
|
+
return 'Transfer';
|
|
3273
|
+
}
|
|
3274
|
+
isSyntheticEventLogAccount(account, provider, expectedId) {
|
|
3275
|
+
return (this.readOptionalScalarField(account, 'owner') === null &&
|
|
3276
|
+
this.readOptionalScalarField(account, 'provider') === provider &&
|
|
3277
|
+
this.readScalarField(account, 'id') === expectedId);
|
|
3278
|
+
}
|
|
3004
3279
|
compareNumericStrings(left, right) {
|
|
3005
3280
|
const leftValue = left === null ? Number.NEGATIVE_INFINITY : Number(left);
|
|
3006
3281
|
const rightValue = right === null ? Number.NEGATIVE_INFINITY : Number(right);
|
|
@@ -3198,9 +3473,43 @@ let PqsSummaryService = class PqsSummaryService {
|
|
|
3198
3473
|
};
|
|
3199
3474
|
}
|
|
3200
3475
|
async fetchEventsByUpdateId(node, query, rawUpdateId) {
|
|
3201
|
-
const
|
|
3476
|
+
const eventsByUpdateId = await this.fetchEventsByUpdateIds(node, query, [rawUpdateId]);
|
|
3477
|
+
return eventsByUpdateId.get(rawUpdateId) ?? [];
|
|
3478
|
+
}
|
|
3479
|
+
async fetchEventsByUpdateIds(node, query, rawUpdateIds) {
|
|
3480
|
+
if (rawUpdateIds.length === 0) {
|
|
3481
|
+
return new Map();
|
|
3482
|
+
}
|
|
3483
|
+
const result = await query(updateEventsByUpdateIdsQuery(node, rawUpdateIds));
|
|
3202
3484
|
const rows = result.rows ?? [];
|
|
3203
|
-
|
|
3485
|
+
const onlyRequestedUpdateId = rawUpdateIds.length === 1 ? rawUpdateIds[0] : null;
|
|
3486
|
+
const normalizedRows = await Promise.all(rows.map(async (row) => ({
|
|
3487
|
+
updateId: typeof row.update_id === 'string'
|
|
3488
|
+
? row.update_id
|
|
3489
|
+
: onlyRequestedUpdateId,
|
|
3490
|
+
event: await this.normalizeEventRow(node, row),
|
|
3491
|
+
})));
|
|
3492
|
+
const eventsByUpdateId = new Map();
|
|
3493
|
+
for (const { updateId, event } of normalizedRows) {
|
|
3494
|
+
if (!updateId) {
|
|
3495
|
+
continue;
|
|
3496
|
+
}
|
|
3497
|
+
const existingEvents = eventsByUpdateId.get(updateId);
|
|
3498
|
+
if (existingEvents) {
|
|
3499
|
+
existingEvents.push(event);
|
|
3500
|
+
}
|
|
3501
|
+
else {
|
|
3502
|
+
eventsByUpdateId.set(updateId, [event]);
|
|
3503
|
+
}
|
|
3504
|
+
}
|
|
3505
|
+
return eventsByUpdateId;
|
|
3506
|
+
}
|
|
3507
|
+
async fetchContractDetailsByIds(node, query, contractIds) {
|
|
3508
|
+
if (contractIds.length === 0) {
|
|
3509
|
+
return [];
|
|
3510
|
+
}
|
|
3511
|
+
const result = await query(contractDetailsQuery(node, contractIds));
|
|
3512
|
+
return result.rows ?? [];
|
|
3204
3513
|
}
|
|
3205
3514
|
shouldResolveRewardCoupon(events) {
|
|
3206
3515
|
return events.some((event) => event.choice === 'ReceiveSvRewardCoupon');
|
|
@@ -3497,6 +3806,66 @@ let PqsSummaryService = class PqsSummaryService {
|
|
|
3497
3806
|
}
|
|
3498
3807
|
return null;
|
|
3499
3808
|
}
|
|
3809
|
+
readOptionalScalarField(value, label) {
|
|
3810
|
+
const field = value.fields.find((candidate) => candidate.label === label)?.value;
|
|
3811
|
+
if (field === null || field === undefined) {
|
|
3812
|
+
return null;
|
|
3813
|
+
}
|
|
3814
|
+
if (typeof field === 'string' || typeof field === 'number' || typeof field === 'boolean') {
|
|
3815
|
+
return String(field);
|
|
3816
|
+
}
|
|
3817
|
+
if (typeof field === 'object' &&
|
|
3818
|
+
field !== null &&
|
|
3819
|
+
'kind' in field &&
|
|
3820
|
+
field.kind === 'contract_id') {
|
|
3821
|
+
return field.value;
|
|
3822
|
+
}
|
|
3823
|
+
if (typeof field !== 'object' || !('kind' in field) || field.kind !== 'optional') {
|
|
3824
|
+
return null;
|
|
3825
|
+
}
|
|
3826
|
+
const innerValue = field.value;
|
|
3827
|
+
if (typeof innerValue === 'string' ||
|
|
3828
|
+
typeof innerValue === 'number' ||
|
|
3829
|
+
typeof innerValue === 'boolean') {
|
|
3830
|
+
return String(innerValue);
|
|
3831
|
+
}
|
|
3832
|
+
if (typeof innerValue === 'object' &&
|
|
3833
|
+
innerValue !== null &&
|
|
3834
|
+
'kind' in innerValue &&
|
|
3835
|
+
innerValue.kind === 'contract_id') {
|
|
3836
|
+
return innerValue.value;
|
|
3837
|
+
}
|
|
3838
|
+
return null;
|
|
3839
|
+
}
|
|
3840
|
+
readConstructorField(value, label) {
|
|
3841
|
+
const field = value.fields.find((candidate) => candidate.label === label)?.value;
|
|
3842
|
+
if (field === null || field === undefined) {
|
|
3843
|
+
return null;
|
|
3844
|
+
}
|
|
3845
|
+
if (typeof field === 'string' || typeof field === 'number' || typeof field === 'boolean') {
|
|
3846
|
+
return String(field);
|
|
3847
|
+
}
|
|
3848
|
+
if (typeof field !== 'object' || !('kind' in field)) {
|
|
3849
|
+
return null;
|
|
3850
|
+
}
|
|
3851
|
+
if (field.kind === 'enum') {
|
|
3852
|
+
return field.constructor;
|
|
3853
|
+
}
|
|
3854
|
+
if (field.kind === 'variant') {
|
|
3855
|
+
return field.constructor;
|
|
3856
|
+
}
|
|
3857
|
+
return null;
|
|
3858
|
+
}
|
|
3859
|
+
readListField(value, label) {
|
|
3860
|
+
const field = value.fields.find((candidate) => candidate.label === label)?.value;
|
|
3861
|
+
if (!field || typeof field !== 'object' || !('kind' in field) || field.kind !== 'list') {
|
|
3862
|
+
return [];
|
|
3863
|
+
}
|
|
3864
|
+
return field.items;
|
|
3865
|
+
}
|
|
3866
|
+
readAccountParty(value) {
|
|
3867
|
+
return this.readOptionalScalarField(value, 'owner') ?? this.readOptionalScalarField(value, 'provider');
|
|
3868
|
+
}
|
|
3500
3869
|
readTextMapEntryField(value, path, key) {
|
|
3501
3870
|
let current = value;
|
|
3502
3871
|
for (const segment of path) {
|