@canton-network/core-tx-parser 0.1.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.
- package/README.md +1 -0
- package/dist/constants.d.ts +14 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/index.cjs +1019 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +997 -0
- package/dist/index.js.map +1 -0
- package/dist/instrumentmap.d.ts +18 -0
- package/dist/instrumentmap.d.ts.map +1 -0
- package/dist/parser.d.ts +29 -0
- package/dist/parser.d.ts.map +1 -0
- package/dist/strict.d.ts +3 -0
- package/dist/strict.d.ts.map +1 -0
- package/dist/types.d.ts +172 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/utils.d.ts +36 -0
- package/dist/utils.d.ts.map +1 -0
- package/package.json +63 -0
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,1019 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var coreTokenStandard = require('@canton-network/core-token-standard');
|
|
4
|
+
var coreLedgerClientTypes = require('@canton-network/core-ledger-client-types');
|
|
5
|
+
var BigNumber = require('bignumber.js');
|
|
6
|
+
|
|
7
|
+
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
8
|
+
|
|
9
|
+
var BigNumber__default = /*#__PURE__*/_interopDefault(BigNumber);
|
|
10
|
+
|
|
11
|
+
var __defProp = Object.defineProperty;
|
|
12
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
13
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
14
|
+
function splitInterfaceId(interfaceId) {
|
|
15
|
+
const regExp = /^#?([^:]+):([^:]+):([^:]+)$/;
|
|
16
|
+
const match = regExp.exec(interfaceId);
|
|
17
|
+
if (!match) return null;
|
|
18
|
+
const [, packageName, moduleName, entityName] = match;
|
|
19
|
+
return {
|
|
20
|
+
packageName,
|
|
21
|
+
moduleName,
|
|
22
|
+
entityName
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
function matchInterfaceIds(a, b) {
|
|
26
|
+
const aParts = splitInterfaceId(a);
|
|
27
|
+
const bParts = splitInterfaceId(b);
|
|
28
|
+
return aParts !== null && bParts !== null && aParts.moduleName === bParts.moduleName && aParts.entityName === bParts.entityName;
|
|
29
|
+
}
|
|
30
|
+
var TokenStandardTransactionInterfaces = [
|
|
31
|
+
coreTokenStandard.HOLDING_INTERFACE_ID,
|
|
32
|
+
coreTokenStandard.TRANSFER_FACTORY_INTERFACE_ID,
|
|
33
|
+
coreTokenStandard.TRANSFER_INSTRUCTION_INTERFACE_ID,
|
|
34
|
+
coreTokenStandard.ALLOCATION_FACTORY_INTERFACE_ID,
|
|
35
|
+
coreTokenStandard.ALLOCATION_INSTRUCTION_INTERFACE_ID,
|
|
36
|
+
coreTokenStandard.ALLOCATION_INTERFACE_ID,
|
|
37
|
+
coreTokenStandard.ALLOCATION_REQUEST_INTERFACE_ID
|
|
38
|
+
];
|
|
39
|
+
var SpliceMetaKeyPrefix = "splice.lfdecentralizedtrust.org/";
|
|
40
|
+
var TxKindMetaKey = `${SpliceMetaKeyPrefix}tx-kind`;
|
|
41
|
+
var SenderMetaKey = `${SpliceMetaKeyPrefix}sender`;
|
|
42
|
+
var ReasonMetaKey = `${SpliceMetaKeyPrefix}reason`;
|
|
43
|
+
var BurnedMetaKey = `${SpliceMetaKeyPrefix}burned`;
|
|
44
|
+
var AllKnownMetaKeys = [
|
|
45
|
+
TxKindMetaKey,
|
|
46
|
+
SenderMetaKey,
|
|
47
|
+
ReasonMetaKey,
|
|
48
|
+
BurnedMetaKey
|
|
49
|
+
];
|
|
50
|
+
function hasInterface(interfaceId, event) {
|
|
51
|
+
return (event.implementedInterfaces || []).some(
|
|
52
|
+
(id) => matchInterfaceIds(id, interfaceId)
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
function getInterfaceView(createdEvent) {
|
|
56
|
+
const interfaceViews = createdEvent.interfaceViews || null;
|
|
57
|
+
return interfaceViews && interfaceViews[0] || null;
|
|
58
|
+
}
|
|
59
|
+
function getKnownInterfaceView(createdEvent) {
|
|
60
|
+
const interfaceView = getInterfaceView(createdEvent);
|
|
61
|
+
if (!interfaceView) {
|
|
62
|
+
return null;
|
|
63
|
+
} else if (matchInterfaceIds(coreTokenStandard.HOLDING_INTERFACE_ID, interfaceView.interfaceId)) {
|
|
64
|
+
return {
|
|
65
|
+
type: "Holding",
|
|
66
|
+
viewValue: interfaceView.viewValue
|
|
67
|
+
};
|
|
68
|
+
} else if (matchInterfaceIds(
|
|
69
|
+
coreTokenStandard.TRANSFER_INSTRUCTION_INTERFACE_ID,
|
|
70
|
+
interfaceView.interfaceId
|
|
71
|
+
)) {
|
|
72
|
+
return {
|
|
73
|
+
type: "TransferInstruction",
|
|
74
|
+
viewValue: interfaceView.viewValue
|
|
75
|
+
};
|
|
76
|
+
} else {
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
function ensureInterfaceViewIsPresent(createdEvent, interfaceId) {
|
|
81
|
+
const interfaceView = getInterfaceView(createdEvent);
|
|
82
|
+
if (!interfaceView) {
|
|
83
|
+
throw new Error(
|
|
84
|
+
`Expected to have interface views, but didn't: ${JSON.stringify(
|
|
85
|
+
createdEvent
|
|
86
|
+
)}`
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
if (!matchInterfaceIds(interfaceId, interfaceView.interfaceId)) {
|
|
90
|
+
throw new Error(
|
|
91
|
+
`Not a ${interfaceId} but a ${interfaceView.interfaceId}: ${JSON.stringify(createdEvent)}`
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
return interfaceView;
|
|
95
|
+
}
|
|
96
|
+
function mergeMetas(event, extra) {
|
|
97
|
+
const choiceArgument = event.choiceArgument;
|
|
98
|
+
const lastWriteWins = [
|
|
99
|
+
choiceArgument?.transfer?.meta,
|
|
100
|
+
choiceArgument?.extraArgs?.meta,
|
|
101
|
+
choiceArgument?.meta,
|
|
102
|
+
extra,
|
|
103
|
+
event.exerciseResult?.meta
|
|
104
|
+
];
|
|
105
|
+
const result = {};
|
|
106
|
+
lastWriteWins.forEach((meta) => {
|
|
107
|
+
const values = meta?.values || {};
|
|
108
|
+
Object.entries(values).forEach(([k, v]) => {
|
|
109
|
+
result[k] = v;
|
|
110
|
+
});
|
|
111
|
+
});
|
|
112
|
+
if (Object.keys(result).length === 0) {
|
|
113
|
+
return void 0;
|
|
114
|
+
} else {
|
|
115
|
+
return { values: result };
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
function getMetaKeyValue(key, meta) {
|
|
119
|
+
return (meta?.values || {})[key] || null;
|
|
120
|
+
}
|
|
121
|
+
function removeParsedMetaKeys(meta) {
|
|
122
|
+
return {
|
|
123
|
+
values: Object.fromEntries(
|
|
124
|
+
Object.entries(meta?.values || {}).filter(
|
|
125
|
+
([k]) => !AllKnownMetaKeys.includes(k)
|
|
126
|
+
)
|
|
127
|
+
)
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// src/types.ts
|
|
132
|
+
var renderTransaction = (t) => {
|
|
133
|
+
return { ...t, events: t.events.map(renderTransactionEvent) };
|
|
134
|
+
};
|
|
135
|
+
var renderTransactionEvent = (e) => {
|
|
136
|
+
const lockedHoldingsChangeSummaries = e.lockedHoldingsChangeSummaries.map(renderHoldingsChangeSummary).filter((s) => s !== null);
|
|
137
|
+
const unlockedHoldingsChangeSummaries = e.unlockedHoldingsChangeSummaries.map(renderHoldingsChangeSummary).filter((s) => s !== null);
|
|
138
|
+
const lockedHoldingsChange = renderHoldingsChange(e.lockedHoldingsChange);
|
|
139
|
+
const unlockedHoldingsChange = renderHoldingsChange(
|
|
140
|
+
e.unlockedHoldingsChange
|
|
141
|
+
);
|
|
142
|
+
return {
|
|
143
|
+
...e,
|
|
144
|
+
lockedHoldingsChange,
|
|
145
|
+
unlockedHoldingsChange,
|
|
146
|
+
lockedHoldingsChangeSummaries,
|
|
147
|
+
// Deprecated
|
|
148
|
+
lockedHoldingsChangeSummary: renderHoldingsChangeSummary(
|
|
149
|
+
e.lockedHoldingsChangeSummary
|
|
150
|
+
),
|
|
151
|
+
unlockedHoldingsChangeSummaries,
|
|
152
|
+
// Deprecated
|
|
153
|
+
unlockedHoldingsChangeSummary: renderHoldingsChangeSummary(
|
|
154
|
+
e.unlockedHoldingsChangeSummary
|
|
155
|
+
)
|
|
156
|
+
};
|
|
157
|
+
};
|
|
158
|
+
var renderHoldingsChangeSummary = (s) => {
|
|
159
|
+
if (s.numInputs === 0 && s.numOutputs === 0 && s.inputAmount === "0" && s.outputAmount === "0" && s.amountChange === "0") {
|
|
160
|
+
return null;
|
|
161
|
+
}
|
|
162
|
+
return {
|
|
163
|
+
...(s.instrumentId.admin !== "" || s.instrumentId.id !== "") && {
|
|
164
|
+
instrumentId: s.instrumentId
|
|
165
|
+
},
|
|
166
|
+
...s.numInputs !== 0 && { numInputs: s.numInputs },
|
|
167
|
+
...s.inputAmount !== "0" && { inputAmount: s.inputAmount },
|
|
168
|
+
...s.numOutputs !== 0 && { numOutputs: s.numOutputs },
|
|
169
|
+
...s.outputAmount !== "0" && { outputAmount: s.outputAmount },
|
|
170
|
+
...s.amountChange !== "0" && { amountChange: s.amountChange }
|
|
171
|
+
};
|
|
172
|
+
};
|
|
173
|
+
var renderHoldingsChange = (c) => {
|
|
174
|
+
if (c.creates.length === 0 && c.archives.length === 0) {
|
|
175
|
+
return null;
|
|
176
|
+
}
|
|
177
|
+
return {
|
|
178
|
+
...c.creates.length !== 0 && { creates: c.creates },
|
|
179
|
+
...c.archives.length !== 0 && { archives: c.archives }
|
|
180
|
+
};
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
// src/instrumentmap.ts
|
|
184
|
+
var InstrumentMap = class {
|
|
185
|
+
constructor() {
|
|
186
|
+
__publicField(this, "map");
|
|
187
|
+
this.map = /* @__PURE__ */ new Map();
|
|
188
|
+
}
|
|
189
|
+
encodeKey(instrumentId) {
|
|
190
|
+
return JSON.stringify([instrumentId.admin, instrumentId.id]);
|
|
191
|
+
}
|
|
192
|
+
decodeKey(key) {
|
|
193
|
+
const [admin, id] = JSON.parse(key);
|
|
194
|
+
return { admin, id };
|
|
195
|
+
}
|
|
196
|
+
set(key, value) {
|
|
197
|
+
this.map.set(this.encodeKey(key), value);
|
|
198
|
+
}
|
|
199
|
+
get(key) {
|
|
200
|
+
return this.map.get(this.encodeKey(key));
|
|
201
|
+
}
|
|
202
|
+
has(key) {
|
|
203
|
+
return this.map.has(this.encodeKey(key));
|
|
204
|
+
}
|
|
205
|
+
delete(key) {
|
|
206
|
+
return this.map.delete(this.encodeKey(key));
|
|
207
|
+
}
|
|
208
|
+
*entries() {
|
|
209
|
+
for (const [key, value] of this.map.entries()) {
|
|
210
|
+
yield [this.decodeKey(key), value];
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
};
|
|
214
|
+
function currentStatusFromChoiceOrResult(choice, resultTag) {
|
|
215
|
+
if (resultTag === "TransferInstructionResult_Failed") return "Failed";
|
|
216
|
+
if (resultTag === "TransferInstructionResult_Completed") return "Completed";
|
|
217
|
+
switch (choice) {
|
|
218
|
+
case "TransferInstruction_Reject":
|
|
219
|
+
return "Rejected";
|
|
220
|
+
case "TransferInstruction_Withdraw":
|
|
221
|
+
return "Withdrawn";
|
|
222
|
+
case "TransferInstruction_Accept":
|
|
223
|
+
case "TransferInstruction_Update":
|
|
224
|
+
return "Pending";
|
|
225
|
+
default:
|
|
226
|
+
return "Pending";
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
function getCorrelationIdFromTransferInstruction(currentInstructionCid, originalInstructionCid) {
|
|
230
|
+
return originalInstructionCid ?? currentInstructionCid;
|
|
231
|
+
}
|
|
232
|
+
function getPendingTransferInstructionCid(exercisedEvent) {
|
|
233
|
+
const output = exercisedEvent.exerciseResult?.output;
|
|
234
|
+
if (output?.tag !== "TransferInstructionResult_Pending") return void 0;
|
|
235
|
+
const cid = output.value?.transferInstructionCid;
|
|
236
|
+
return cid ?? void 0;
|
|
237
|
+
}
|
|
238
|
+
function isTransferObject(value) {
|
|
239
|
+
if (!value || typeof value !== "object") return false;
|
|
240
|
+
const v = value;
|
|
241
|
+
const instrumentId = v.instrumentId;
|
|
242
|
+
const meta = v.meta;
|
|
243
|
+
return typeof v.sender === "string" && typeof v.receiver === "string" && typeof v.amount === "string" && typeof v.requestedAt === "string" && typeof v.executeBefore === "string" && Array.isArray(v.inputHoldingCids) && v.inputHoldingCids.every((cid) => typeof cid === "string") && !!instrumentId && typeof instrumentId.admin === "string" && typeof instrumentId.id === "string" && !!meta && typeof meta.values === "object" && meta.values !== null;
|
|
244
|
+
}
|
|
245
|
+
var TransactionParser = class {
|
|
246
|
+
constructor(transaction, ledgerClient, partyId, isMasterUser) {
|
|
247
|
+
__publicField(this, "ledgerClient");
|
|
248
|
+
__publicField(this, "partyId");
|
|
249
|
+
__publicField(this, "transaction");
|
|
250
|
+
__publicField(this, "isMasterUser");
|
|
251
|
+
this.ledgerClient = ledgerClient;
|
|
252
|
+
this.partyId = partyId;
|
|
253
|
+
this.transaction = transaction;
|
|
254
|
+
this.isMasterUser = isMasterUser;
|
|
255
|
+
}
|
|
256
|
+
async parseTransaction() {
|
|
257
|
+
const tx = this.transaction;
|
|
258
|
+
const events = await this.parseEvents([...tx.events || []].reverse());
|
|
259
|
+
return {
|
|
260
|
+
updateId: tx.updateId,
|
|
261
|
+
offset: tx.offset,
|
|
262
|
+
recordTime: tx.recordTime,
|
|
263
|
+
synchronizerId: tx.synchronizerId,
|
|
264
|
+
events
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
async parseTransferObjects() {
|
|
268
|
+
const eventsStack = [...this.transaction.events || []].reverse();
|
|
269
|
+
const results = await this.fetchTransferObjectChoice(eventsStack);
|
|
270
|
+
return results;
|
|
271
|
+
}
|
|
272
|
+
async fetchTransferObjectChoice(eventsStack) {
|
|
273
|
+
const result = [];
|
|
274
|
+
while (eventsStack.length > 0) {
|
|
275
|
+
const currentEvent = eventsStack.pop();
|
|
276
|
+
const { exercisedEvent } = getNodeIdAndEvent(currentEvent);
|
|
277
|
+
if (exercisedEvent && (exercisedEvent.choice === "TransferFactory_Transfer" || exercisedEvent.choice === "TransferRule_Transfer")) {
|
|
278
|
+
const { choiceArgument } = exercisedEvent;
|
|
279
|
+
if (choiceArgument && typeof choiceArgument === "object" && "transfer" in choiceArgument) {
|
|
280
|
+
const transfer = choiceArgument.transfer;
|
|
281
|
+
if (isTransferObject(transfer)) {
|
|
282
|
+
result.push(transfer);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
return result;
|
|
288
|
+
}
|
|
289
|
+
async parseEvents(eventsStack) {
|
|
290
|
+
let callStack = [];
|
|
291
|
+
let continueAfterNodeId = -1;
|
|
292
|
+
const result = [];
|
|
293
|
+
while (eventsStack.length > 0) {
|
|
294
|
+
const currentEvent = eventsStack.pop();
|
|
295
|
+
const { nodeId, createdEvent, archivedEvent, exercisedEvent } = getNodeIdAndEvent(currentEvent);
|
|
296
|
+
callStack = callStack.filter((s) => s.untilNodeId <= nodeId);
|
|
297
|
+
const parentChoice = callStack[callStack.length - 1] && callStack[callStack.length - 1].parentChoiceName || "none (root node)";
|
|
298
|
+
let parsed;
|
|
299
|
+
if (nodeId <= continueAfterNodeId) {
|
|
300
|
+
parsed = null;
|
|
301
|
+
} else if (createdEvent) {
|
|
302
|
+
parsed = this.parseRawCreate(createdEvent, parentChoice);
|
|
303
|
+
} else if (archivedEvent) {
|
|
304
|
+
parsed = await this.parseRawArchive(archivedEvent, parentChoice);
|
|
305
|
+
} else if (exercisedEvent) {
|
|
306
|
+
parsed = await this.parseExercise(exercisedEvent);
|
|
307
|
+
} else {
|
|
308
|
+
throw new Error(
|
|
309
|
+
`Impossible event: ${JSON.stringify(currentEvent)}`
|
|
310
|
+
);
|
|
311
|
+
}
|
|
312
|
+
if (parsed && isLeafEventNode(parsed)) {
|
|
313
|
+
if (holdingChangesNonEmpty(parsed.event)) {
|
|
314
|
+
result.push({
|
|
315
|
+
...parsed.event,
|
|
316
|
+
label: {
|
|
317
|
+
...parsed.event.label,
|
|
318
|
+
meta: removeParsedMetaKeys(parsed.event.label.meta)
|
|
319
|
+
}
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
continueAfterNodeId = parsed.continueAfterNodeId;
|
|
323
|
+
} else if (parsed) {
|
|
324
|
+
callStack.push({
|
|
325
|
+
parentChoiceName: parsed.parentChoiceName,
|
|
326
|
+
untilNodeId: parsed.lastDescendantNodeId
|
|
327
|
+
});
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
return result;
|
|
331
|
+
}
|
|
332
|
+
parseRawCreate(create, parentChoice) {
|
|
333
|
+
return this.buildRawEvent(create, create.nodeId, (result) => {
|
|
334
|
+
return {
|
|
335
|
+
// TODO: this code currently only looks at the first instrument
|
|
336
|
+
// to determine the type of the Event.
|
|
337
|
+
type: Number(
|
|
338
|
+
result.lockedHoldingsChangeSummaries[0]?.amountChange
|
|
339
|
+
) > 0 ? "Lock" : "Create",
|
|
340
|
+
parentChoice,
|
|
341
|
+
contractId: create.contractId,
|
|
342
|
+
offset: create.offset,
|
|
343
|
+
templateId: create.templateId,
|
|
344
|
+
payload: result.payload,
|
|
345
|
+
packageName: create.packageName,
|
|
346
|
+
meta: void 0
|
|
347
|
+
};
|
|
348
|
+
});
|
|
349
|
+
}
|
|
350
|
+
async parseRawArchive(archive, parentChoice) {
|
|
351
|
+
const events = await this.getEventsForArchive(archive);
|
|
352
|
+
if (!events) {
|
|
353
|
+
return null;
|
|
354
|
+
}
|
|
355
|
+
return this.buildRawEvent(
|
|
356
|
+
events.created.createdEvent,
|
|
357
|
+
archive.nodeId,
|
|
358
|
+
(result) => {
|
|
359
|
+
return {
|
|
360
|
+
type: "Archive",
|
|
361
|
+
parentChoice,
|
|
362
|
+
contractId: archive.contractId,
|
|
363
|
+
offset: archive.offset,
|
|
364
|
+
templateId: archive.templateId,
|
|
365
|
+
packageName: archive.packageName,
|
|
366
|
+
actingParties: archive.actingParties || [],
|
|
367
|
+
payload: result.payload,
|
|
368
|
+
meta: void 0
|
|
369
|
+
};
|
|
370
|
+
}
|
|
371
|
+
);
|
|
372
|
+
}
|
|
373
|
+
buildRawEvent(originalCreate, nodeId, buildLabel) {
|
|
374
|
+
const view = getKnownInterfaceView(originalCreate);
|
|
375
|
+
let result;
|
|
376
|
+
switch (view?.type) {
|
|
377
|
+
case "Holding": {
|
|
378
|
+
const holdingView = view.viewValue;
|
|
379
|
+
if (this.partyId !== holdingView.owner) {
|
|
380
|
+
result = null;
|
|
381
|
+
} else {
|
|
382
|
+
const isLocked = !!holdingView.lock;
|
|
383
|
+
const summary = {
|
|
384
|
+
instrumentId: holdingView.instrumentId,
|
|
385
|
+
amountChange: holdingView.amount,
|
|
386
|
+
numInputs: 0,
|
|
387
|
+
inputAmount: "0",
|
|
388
|
+
numOutputs: 1,
|
|
389
|
+
outputAmount: holdingView.amount
|
|
390
|
+
};
|
|
391
|
+
const lockedHoldingsChangeSummaries = isLocked ? [summary] : [];
|
|
392
|
+
const unlockedHoldingsChangeSummaries = isLocked ? [] : [summary];
|
|
393
|
+
result = {
|
|
394
|
+
payload: holdingView,
|
|
395
|
+
unlockedHoldingsChange: {
|
|
396
|
+
creates: isLocked ? [] : [holdingView],
|
|
397
|
+
archives: []
|
|
398
|
+
},
|
|
399
|
+
lockedHoldingsChange: {
|
|
400
|
+
creates: isLocked ? [holdingView] : [],
|
|
401
|
+
archives: []
|
|
402
|
+
},
|
|
403
|
+
lockedHoldingsChangeSummaries,
|
|
404
|
+
lockedHoldingsChangeSummary: lockedHoldingsChangeSummaries[0] ?? emptyHoldingsChangeSummary,
|
|
405
|
+
unlockedHoldingsChangeSummaries,
|
|
406
|
+
unlockedHoldingsChangeSummary: unlockedHoldingsChangeSummaries[0] ?? emptyHoldingsChangeSummary,
|
|
407
|
+
transferInstruction: null
|
|
408
|
+
};
|
|
409
|
+
}
|
|
410
|
+
break;
|
|
411
|
+
}
|
|
412
|
+
case "TransferInstruction": {
|
|
413
|
+
const transferInstructionView = view.viewValue;
|
|
414
|
+
if (![
|
|
415
|
+
transferInstructionView.transfer.sender,
|
|
416
|
+
transferInstructionView.transfer.receiver
|
|
417
|
+
].some((stakeholder) => stakeholder === this.partyId)) {
|
|
418
|
+
result = null;
|
|
419
|
+
} else {
|
|
420
|
+
const multiStepCorrelationId = getCorrelationIdFromTransferInstruction(
|
|
421
|
+
originalCreate.contractId,
|
|
422
|
+
transferInstructionView.originalInstructionCid ?? null
|
|
423
|
+
);
|
|
424
|
+
result = {
|
|
425
|
+
payload: transferInstructionView,
|
|
426
|
+
transferInstruction: {
|
|
427
|
+
originalInstructionCid: transferInstructionView.originalInstructionCid,
|
|
428
|
+
transfer: transferInstructionView.transfer,
|
|
429
|
+
meta: transferInstructionView.meta,
|
|
430
|
+
status: {
|
|
431
|
+
before: transferInstructionView.status,
|
|
432
|
+
// raw DAML pending sub-state
|
|
433
|
+
current: { tag: "Pending", value: {} }
|
|
434
|
+
// normalized
|
|
435
|
+
},
|
|
436
|
+
multiStepCorrelationId
|
|
437
|
+
},
|
|
438
|
+
unlockedHoldingsChange: { creates: [], archives: [] },
|
|
439
|
+
lockedHoldingsChange: { creates: [], archives: [] },
|
|
440
|
+
unlockedHoldingsChangeSummaries: [],
|
|
441
|
+
unlockedHoldingsChangeSummary: emptyHoldingsChangeSummary,
|
|
442
|
+
lockedHoldingsChangeSummaries: [],
|
|
443
|
+
lockedHoldingsChangeSummary: emptyHoldingsChangeSummary
|
|
444
|
+
};
|
|
445
|
+
}
|
|
446
|
+
break;
|
|
447
|
+
}
|
|
448
|
+
default:
|
|
449
|
+
result = null;
|
|
450
|
+
}
|
|
451
|
+
return result && {
|
|
452
|
+
continueAfterNodeId: nodeId,
|
|
453
|
+
event: {
|
|
454
|
+
label: buildLabel(result),
|
|
455
|
+
unlockedHoldingsChange: result.unlockedHoldingsChange,
|
|
456
|
+
lockedHoldingsChange: result.lockedHoldingsChange,
|
|
457
|
+
lockedHoldingsChangeSummaries: result.lockedHoldingsChangeSummaries,
|
|
458
|
+
lockedHoldingsChangeSummary: result.lockedHoldingsChangeSummary,
|
|
459
|
+
unlockedHoldingsChangeSummaries: result.unlockedHoldingsChangeSummaries,
|
|
460
|
+
unlockedHoldingsChangeSummary: result.unlockedHoldingsChangeSummary,
|
|
461
|
+
transferInstruction: result.transferInstruction
|
|
462
|
+
}
|
|
463
|
+
};
|
|
464
|
+
}
|
|
465
|
+
async parseExercise(exercise) {
|
|
466
|
+
let result = null;
|
|
467
|
+
const tokenStandardChoice = {
|
|
468
|
+
name: exercise.choice,
|
|
469
|
+
choiceArgument: exercise.choiceArgument,
|
|
470
|
+
exerciseResult: exercise.exerciseResult
|
|
471
|
+
};
|
|
472
|
+
switch (exercise.choice) {
|
|
473
|
+
case "TransferRule_Transfer":
|
|
474
|
+
case "TransferFactory_Transfer":
|
|
475
|
+
result = await this.buildTransfer(exercise, tokenStandardChoice);
|
|
476
|
+
break;
|
|
477
|
+
case "TransferInstruction_Accept":
|
|
478
|
+
case "TransferInstruction_Reject":
|
|
479
|
+
case "TransferInstruction_Withdraw":
|
|
480
|
+
case "TransferInstruction_Update":
|
|
481
|
+
result = await this.buildFromTransferInstructionExercise(
|
|
482
|
+
exercise,
|
|
483
|
+
tokenStandardChoice
|
|
484
|
+
);
|
|
485
|
+
break;
|
|
486
|
+
case "BurnMintFactory_BurnMint":
|
|
487
|
+
result = await this.buildMergeSplit(
|
|
488
|
+
exercise,
|
|
489
|
+
tokenStandardChoice
|
|
490
|
+
);
|
|
491
|
+
break;
|
|
492
|
+
default: {
|
|
493
|
+
const meta = mergeMetas(exercise);
|
|
494
|
+
const txKind = getMetaKeyValue(TxKindMetaKey, meta);
|
|
495
|
+
if (txKind) {
|
|
496
|
+
result = await this.parseViaTxKind(exercise, txKind);
|
|
497
|
+
}
|
|
498
|
+
break;
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
if (!result) {
|
|
502
|
+
return {
|
|
503
|
+
lastDescendantNodeId: exercise.lastDescendantNodeId,
|
|
504
|
+
parentChoiceName: exercise.choice
|
|
505
|
+
};
|
|
506
|
+
} else {
|
|
507
|
+
const lockedHoldingsChange = {
|
|
508
|
+
creates: result.children.creates.filter(
|
|
509
|
+
(h) => !!h.lock && h.owner === this.partyId
|
|
510
|
+
),
|
|
511
|
+
archives: result.children.archives.filter(
|
|
512
|
+
(h) => !!h.lock && h.owner === this.partyId
|
|
513
|
+
)
|
|
514
|
+
};
|
|
515
|
+
const unlockedHoldingsChange = {
|
|
516
|
+
creates: result.children.creates.filter(
|
|
517
|
+
(h) => !h.lock && h.owner === this.partyId
|
|
518
|
+
),
|
|
519
|
+
archives: result.children.archives.filter(
|
|
520
|
+
(h) => !h.lock && h.owner === this.partyId
|
|
521
|
+
)
|
|
522
|
+
};
|
|
523
|
+
const lockedHoldingsChangeSummaries = computeSummaries(
|
|
524
|
+
lockedHoldingsChange,
|
|
525
|
+
this.partyId
|
|
526
|
+
);
|
|
527
|
+
const unlockedHoldingsChangeSummaries = computeSummaries(
|
|
528
|
+
unlockedHoldingsChange,
|
|
529
|
+
this.partyId
|
|
530
|
+
);
|
|
531
|
+
return {
|
|
532
|
+
event: {
|
|
533
|
+
label: result.label,
|
|
534
|
+
lockedHoldingsChange,
|
|
535
|
+
lockedHoldingsChangeSummaries,
|
|
536
|
+
lockedHoldingsChangeSummary: lockedHoldingsChangeSummaries[0] ?? emptyHoldingsChangeSummary,
|
|
537
|
+
unlockedHoldingsChange,
|
|
538
|
+
unlockedHoldingsChangeSummaries,
|
|
539
|
+
unlockedHoldingsChangeSummary: unlockedHoldingsChangeSummaries[0] ?? emptyHoldingsChangeSummary,
|
|
540
|
+
transferInstruction: result.transferInstruction
|
|
541
|
+
},
|
|
542
|
+
continueAfterNodeId: exercise.lastDescendantNodeId
|
|
543
|
+
};
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
async parseViaTxKind(exercisedEvent, txKind) {
|
|
547
|
+
switch (txKind) {
|
|
548
|
+
case "transfer":
|
|
549
|
+
return await this.buildTransfer(exercisedEvent, null);
|
|
550
|
+
case "merge-split":
|
|
551
|
+
case "burn":
|
|
552
|
+
case "mint":
|
|
553
|
+
return await this.buildMergeSplit(exercisedEvent, null);
|
|
554
|
+
case "unlock":
|
|
555
|
+
return await this.buildBasic(exercisedEvent, "Unlock", null);
|
|
556
|
+
case "expire-dust":
|
|
557
|
+
return await this.buildBasic(exercisedEvent, "ExpireDust", null);
|
|
558
|
+
default:
|
|
559
|
+
throw new Error(
|
|
560
|
+
`Unknown tx-kind '${txKind}' in ${JSON.stringify(exercisedEvent)}`
|
|
561
|
+
);
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
async buildTransfer(exercisedEvent, tokenStandardChoice, transferInstructions) {
|
|
565
|
+
const meta = mergeMetas(
|
|
566
|
+
exercisedEvent,
|
|
567
|
+
transferInstructions?.transfer?.meta
|
|
568
|
+
);
|
|
569
|
+
const reason = getMetaKeyValue(ReasonMetaKey, meta);
|
|
570
|
+
const choiceArgumentTransfer = exercisedEvent.choiceArgument.transfer;
|
|
571
|
+
const sender = transferInstructions?.transfer?.sender || getMetaKeyValue(SenderMetaKey, meta) || choiceArgumentTransfer.sender;
|
|
572
|
+
if (!sender) {
|
|
573
|
+
console.error(
|
|
574
|
+
`Malformed transfer didn't contain sender. Will instead attempt to parse the children.
|
|
575
|
+
Transfer: ${JSON.stringify(exercisedEvent)}`
|
|
576
|
+
);
|
|
577
|
+
return null;
|
|
578
|
+
}
|
|
579
|
+
const resultTag = exercisedEvent.exerciseResult?.output?.tag || void 0;
|
|
580
|
+
const pendingCid = getPendingTransferInstructionCid(exercisedEvent);
|
|
581
|
+
const currentTag = currentStatusFromChoiceOrResult(
|
|
582
|
+
exercisedEvent.choice,
|
|
583
|
+
resultTag
|
|
584
|
+
);
|
|
585
|
+
const children = await this.getChildren(exercisedEvent);
|
|
586
|
+
const receiverAmounts = /* @__PURE__ */ new Map();
|
|
587
|
+
children.creates.filter((h) => h.owner !== sender).forEach(
|
|
588
|
+
(holding) => receiverAmounts.set(
|
|
589
|
+
holding.owner,
|
|
590
|
+
(receiverAmounts.get(holding.owner) || BigNumber__default.default("0")).plus(
|
|
591
|
+
BigNumber__default.default(holding.amount)
|
|
592
|
+
)
|
|
593
|
+
)
|
|
594
|
+
);
|
|
595
|
+
const amountChanges = computeAmountChanges(children, meta, this.partyId);
|
|
596
|
+
let label;
|
|
597
|
+
if (receiverAmounts.size === 0) {
|
|
598
|
+
label = {
|
|
599
|
+
...amountChanges,
|
|
600
|
+
type: "MergeSplit",
|
|
601
|
+
tokenStandardChoice,
|
|
602
|
+
reason,
|
|
603
|
+
meta
|
|
604
|
+
};
|
|
605
|
+
} else if (sender === this.partyId) {
|
|
606
|
+
label = {
|
|
607
|
+
...amountChanges,
|
|
608
|
+
type: "TransferOut",
|
|
609
|
+
receiverAmounts: [...receiverAmounts].map(([k, v]) => {
|
|
610
|
+
return { receiver: k, amount: v.toString() };
|
|
611
|
+
}),
|
|
612
|
+
tokenStandardChoice,
|
|
613
|
+
reason,
|
|
614
|
+
meta
|
|
615
|
+
};
|
|
616
|
+
} else {
|
|
617
|
+
label = {
|
|
618
|
+
type: "TransferIn",
|
|
619
|
+
// for Transfers, the burn/mint is always 0 for the receiving party (i.e., 0 for TransferIn)
|
|
620
|
+
burnAmount: "0",
|
|
621
|
+
mintAmount: "0",
|
|
622
|
+
sender,
|
|
623
|
+
tokenStandardChoice,
|
|
624
|
+
reason,
|
|
625
|
+
meta
|
|
626
|
+
};
|
|
627
|
+
}
|
|
628
|
+
if (transferInstructions) {
|
|
629
|
+
transferInstructions.status.current = transferInstructions.status.current || { tag: currentTag, value: {} };
|
|
630
|
+
return {
|
|
631
|
+
label,
|
|
632
|
+
children,
|
|
633
|
+
transferInstruction: transferInstructions
|
|
634
|
+
};
|
|
635
|
+
}
|
|
636
|
+
const transferInstruction = {
|
|
637
|
+
originalInstructionCid: null,
|
|
638
|
+
...choiceArgumentTransfer !== void 0 && {
|
|
639
|
+
transfer: choiceArgumentTransfer
|
|
640
|
+
},
|
|
641
|
+
status: {
|
|
642
|
+
before: null,
|
|
643
|
+
current: { tag: currentTag, value: {} }
|
|
644
|
+
},
|
|
645
|
+
meta: null,
|
|
646
|
+
...pendingCid ? { multiStepCorrelationId: pendingCid } : {}
|
|
647
|
+
};
|
|
648
|
+
return {
|
|
649
|
+
label,
|
|
650
|
+
children,
|
|
651
|
+
transferInstruction
|
|
652
|
+
};
|
|
653
|
+
}
|
|
654
|
+
async buildMergeSplit(exercisedEvent, tokenStandardChoice) {
|
|
655
|
+
let type;
|
|
656
|
+
const meta = mergeMetas(exercisedEvent);
|
|
657
|
+
switch (getMetaKeyValue(TxKindMetaKey, meta)) {
|
|
658
|
+
case "burn":
|
|
659
|
+
type = "Burn";
|
|
660
|
+
break;
|
|
661
|
+
case "mint":
|
|
662
|
+
type = "Mint";
|
|
663
|
+
break;
|
|
664
|
+
default:
|
|
665
|
+
type = "MergeSplit";
|
|
666
|
+
}
|
|
667
|
+
const reason = getMetaKeyValue(ReasonMetaKey, meta);
|
|
668
|
+
const children = await this.getChildren(exercisedEvent);
|
|
669
|
+
const amountChanges = computeAmountChanges(children, meta, this.partyId);
|
|
670
|
+
const label = {
|
|
671
|
+
...amountChanges,
|
|
672
|
+
type,
|
|
673
|
+
tokenStandardChoice,
|
|
674
|
+
reason,
|
|
675
|
+
meta
|
|
676
|
+
};
|
|
677
|
+
return {
|
|
678
|
+
label,
|
|
679
|
+
children,
|
|
680
|
+
transferInstruction: null
|
|
681
|
+
};
|
|
682
|
+
}
|
|
683
|
+
async buildFromTransferInstructionExercise(exercisedEvent, tokenStandardChoice) {
|
|
684
|
+
const instructionCid = exercisedEvent.contractId;
|
|
685
|
+
const transferInstructionEvents = await this.getEventsForArchive(exercisedEvent);
|
|
686
|
+
if (!transferInstructionEvents) {
|
|
687
|
+
return null;
|
|
688
|
+
}
|
|
689
|
+
const transferInstructionView = ensureInterfaceViewIsPresent(
|
|
690
|
+
transferInstructionEvents.created.createdEvent,
|
|
691
|
+
coreTokenStandard.TRANSFER_INSTRUCTION_INTERFACE_ID
|
|
692
|
+
).viewValue;
|
|
693
|
+
const multiStepCorrelationId = getCorrelationIdFromTransferInstruction(
|
|
694
|
+
instructionCid,
|
|
695
|
+
transferInstructionView.originalInstructionCid ?? null
|
|
696
|
+
);
|
|
697
|
+
const resultTag = exercisedEvent.exerciseResult?.output?.tag || void 0;
|
|
698
|
+
const currentTag = currentStatusFromChoiceOrResult(
|
|
699
|
+
exercisedEvent.choice,
|
|
700
|
+
resultTag
|
|
701
|
+
);
|
|
702
|
+
const transferInstruction = {
|
|
703
|
+
originalInstructionCid: transferInstructionView.originalInstructionCid,
|
|
704
|
+
multiStepCorrelationId,
|
|
705
|
+
transfer: transferInstructionView.transfer,
|
|
706
|
+
meta: transferInstructionView.meta,
|
|
707
|
+
status: {
|
|
708
|
+
before: transferInstructionView.status,
|
|
709
|
+
current: { tag: currentTag, value: {} }
|
|
710
|
+
}
|
|
711
|
+
};
|
|
712
|
+
const exerciseResultOutputTag = resultTag;
|
|
713
|
+
let result = null;
|
|
714
|
+
switch (exerciseResultOutputTag) {
|
|
715
|
+
case "TransferInstructionResult_Failed":
|
|
716
|
+
case "TransferInstructionResult_Pending":
|
|
717
|
+
result = await this.buildMergeSplit(
|
|
718
|
+
exercisedEvent,
|
|
719
|
+
tokenStandardChoice
|
|
720
|
+
);
|
|
721
|
+
break;
|
|
722
|
+
case "TransferInstructionResult_Completed":
|
|
723
|
+
result = await this.buildTransfer(
|
|
724
|
+
exercisedEvent,
|
|
725
|
+
tokenStandardChoice,
|
|
726
|
+
transferInstruction
|
|
727
|
+
);
|
|
728
|
+
break;
|
|
729
|
+
default:
|
|
730
|
+
throw new Error(
|
|
731
|
+
`Unknown TransferInstructionResult: ${exerciseResultOutputTag}`
|
|
732
|
+
);
|
|
733
|
+
}
|
|
734
|
+
return result && {
|
|
735
|
+
...result,
|
|
736
|
+
transferInstruction
|
|
737
|
+
};
|
|
738
|
+
}
|
|
739
|
+
async buildBasic(exercisedEvent, type, tokenStandardChoice) {
|
|
740
|
+
const children = await this.getChildren(exercisedEvent);
|
|
741
|
+
const meta = mergeMetas(exercisedEvent);
|
|
742
|
+
const amountChanges = computeAmountChanges(children, meta, this.partyId);
|
|
743
|
+
const reason = getMetaKeyValue(ReasonMetaKey, meta);
|
|
744
|
+
return {
|
|
745
|
+
label: {
|
|
746
|
+
...amountChanges,
|
|
747
|
+
type,
|
|
748
|
+
tokenStandardChoice,
|
|
749
|
+
reason,
|
|
750
|
+
meta
|
|
751
|
+
},
|
|
752
|
+
children,
|
|
753
|
+
transferInstruction: null
|
|
754
|
+
};
|
|
755
|
+
}
|
|
756
|
+
async getChildren(exercisedEvent) {
|
|
757
|
+
const mutatingResult = { creates: [], archives: [] };
|
|
758
|
+
const childrenEventsSlice = (this.transaction.events || []).map(getNodeIdAndEvent).filter(
|
|
759
|
+
({ nodeId }) => nodeId > exercisedEvent.nodeId && nodeId <= exercisedEvent.lastDescendantNodeId
|
|
760
|
+
);
|
|
761
|
+
if (exercisedEvent.consuming && hasInterface(coreTokenStandard.HOLDING_INTERFACE_ID, exercisedEvent)) {
|
|
762
|
+
const selfEvent = await this.getEventsForArchive(exercisedEvent);
|
|
763
|
+
if (selfEvent) {
|
|
764
|
+
const holdingView = ensureInterfaceViewIsPresent(
|
|
765
|
+
selfEvent.created.createdEvent,
|
|
766
|
+
coreTokenStandard.HOLDING_INTERFACE_ID
|
|
767
|
+
).viewValue;
|
|
768
|
+
mutatingResult.archives.push({
|
|
769
|
+
amount: holdingView.amount,
|
|
770
|
+
instrumentId: holdingView.instrumentId,
|
|
771
|
+
contractId: exercisedEvent.contractId,
|
|
772
|
+
owner: holdingView.owner,
|
|
773
|
+
meta: holdingView.meta,
|
|
774
|
+
lock: holdingView.lock
|
|
775
|
+
});
|
|
776
|
+
}
|
|
777
|
+
}
|
|
778
|
+
for (const {
|
|
779
|
+
createdEvent,
|
|
780
|
+
archivedEvent,
|
|
781
|
+
exercisedEvent: exercisedEvent2
|
|
782
|
+
} of childrenEventsSlice) {
|
|
783
|
+
if (createdEvent) {
|
|
784
|
+
const interfaceView = getInterfaceView(createdEvent);
|
|
785
|
+
if (interfaceView && matchInterfaceIds(
|
|
786
|
+
coreTokenStandard.HOLDING_INTERFACE_ID,
|
|
787
|
+
interfaceView.interfaceId
|
|
788
|
+
)) {
|
|
789
|
+
const holdingView = interfaceView.viewValue;
|
|
790
|
+
mutatingResult.creates.push({
|
|
791
|
+
amount: holdingView.amount,
|
|
792
|
+
instrumentId: holdingView.instrumentId,
|
|
793
|
+
contractId: createdEvent.contractId,
|
|
794
|
+
owner: holdingView.owner,
|
|
795
|
+
meta: holdingView.meta,
|
|
796
|
+
lock: holdingView.lock
|
|
797
|
+
});
|
|
798
|
+
}
|
|
799
|
+
} else if (archivedEvent && hasInterface(coreTokenStandard.HOLDING_INTERFACE_ID, archivedEvent) || exercisedEvent2 && exercisedEvent2.consuming && hasInterface(coreTokenStandard.HOLDING_INTERFACE_ID, exercisedEvent2)) {
|
|
800
|
+
const contractEvents = await this.getEventsForArchive(
|
|
801
|
+
archivedEvent || exercisedEvent2
|
|
802
|
+
);
|
|
803
|
+
if (contractEvents) {
|
|
804
|
+
const holdingView = ensureInterfaceViewIsPresent(
|
|
805
|
+
contractEvents.created?.createdEvent,
|
|
806
|
+
coreTokenStandard.HOLDING_INTERFACE_ID
|
|
807
|
+
).viewValue;
|
|
808
|
+
mutatingResult.archives.push({
|
|
809
|
+
amount: holdingView.amount,
|
|
810
|
+
instrumentId: holdingView.instrumentId,
|
|
811
|
+
contractId: archivedEvent?.contractId || exercisedEvent2.contractId,
|
|
812
|
+
owner: holdingView.owner,
|
|
813
|
+
meta: holdingView.meta,
|
|
814
|
+
lock: holdingView.lock
|
|
815
|
+
});
|
|
816
|
+
}
|
|
817
|
+
}
|
|
818
|
+
}
|
|
819
|
+
return {
|
|
820
|
+
// remove transient contracts
|
|
821
|
+
creates: mutatingResult.creates.filter(
|
|
822
|
+
(create) => !mutatingResult.archives.some(
|
|
823
|
+
(archive) => create.contractId === archive.contractId
|
|
824
|
+
)
|
|
825
|
+
),
|
|
826
|
+
archives: mutatingResult.archives.filter(
|
|
827
|
+
(archive) => !mutatingResult.creates.some(
|
|
828
|
+
(create) => create.contractId === archive.contractId
|
|
829
|
+
)
|
|
830
|
+
)
|
|
831
|
+
};
|
|
832
|
+
}
|
|
833
|
+
async getEventsForArchive(archivedEvent) {
|
|
834
|
+
if (!(archivedEvent.witnessParties || []).includes(this.partyId)) {
|
|
835
|
+
return null;
|
|
836
|
+
}
|
|
837
|
+
const basePayload = {
|
|
838
|
+
contractId: archivedEvent.contractId,
|
|
839
|
+
eventFormat: coreLedgerClientTypes.EventFilterBySetup({
|
|
840
|
+
interfaceIds: [
|
|
841
|
+
coreTokenStandard.HOLDING_INTERFACE_ID,
|
|
842
|
+
coreTokenStandard.TRANSFER_INSTRUCTION_INTERFACE_ID
|
|
843
|
+
],
|
|
844
|
+
isMasterUser: this.isMasterUser,
|
|
845
|
+
partyId: this.partyId,
|
|
846
|
+
verbose: true
|
|
847
|
+
})
|
|
848
|
+
};
|
|
849
|
+
const payload = this.ledgerClient.getCurrentClientVersion() === "3.3" ? { ...basePayload, requestingParties: [] } : basePayload;
|
|
850
|
+
const events = await this.ledgerClient.postWithRetry("/v2/events/events-by-contract-id", payload).catch((err) => {
|
|
851
|
+
if (err.code === "CONTRACT_EVENTS_NOT_FOUND") {
|
|
852
|
+
return null;
|
|
853
|
+
} else {
|
|
854
|
+
throw err;
|
|
855
|
+
}
|
|
856
|
+
});
|
|
857
|
+
if (!events) {
|
|
858
|
+
return null;
|
|
859
|
+
}
|
|
860
|
+
const created = events.created;
|
|
861
|
+
const archived = events.archived;
|
|
862
|
+
if (!created || !archived) {
|
|
863
|
+
throw new Error(
|
|
864
|
+
`Archival of ${archivedEvent.contractId} does not have a corresponding create/archive event: ${JSON.stringify(
|
|
865
|
+
events
|
|
866
|
+
)}`
|
|
867
|
+
);
|
|
868
|
+
}
|
|
869
|
+
return { created, archived };
|
|
870
|
+
}
|
|
871
|
+
};
|
|
872
|
+
function isLeafEventNode(result) {
|
|
873
|
+
return !!result.event;
|
|
874
|
+
}
|
|
875
|
+
function getNodeIdAndEvent(event) {
|
|
876
|
+
if ("ExercisedEvent" in event) {
|
|
877
|
+
if (event.ExercisedEvent.choice === "Archive") {
|
|
878
|
+
return {
|
|
879
|
+
nodeId: event.ExercisedEvent.nodeId,
|
|
880
|
+
archivedEvent: event.ExercisedEvent
|
|
881
|
+
};
|
|
882
|
+
} else {
|
|
883
|
+
return {
|
|
884
|
+
nodeId: event.ExercisedEvent.nodeId,
|
|
885
|
+
exercisedEvent: event.ExercisedEvent
|
|
886
|
+
};
|
|
887
|
+
}
|
|
888
|
+
} else if ("CreatedEvent" in event) {
|
|
889
|
+
return {
|
|
890
|
+
nodeId: event.CreatedEvent.nodeId,
|
|
891
|
+
createdEvent: event.CreatedEvent
|
|
892
|
+
};
|
|
893
|
+
} else if ("ArchivedEvent" in event) {
|
|
894
|
+
return {
|
|
895
|
+
nodeId: event.ArchivedEvent.nodeId,
|
|
896
|
+
archivedEvent: event.ArchivedEvent
|
|
897
|
+
};
|
|
898
|
+
} else {
|
|
899
|
+
throw new Error(`Impossible event type: ${event}`);
|
|
900
|
+
}
|
|
901
|
+
}
|
|
902
|
+
function sumHoldingsChange(change, filter) {
|
|
903
|
+
return sumHoldings(
|
|
904
|
+
change.creates.filter((create) => filter(create.owner, create.lock))
|
|
905
|
+
).minus(
|
|
906
|
+
sumHoldings(
|
|
907
|
+
change.archives.filter(
|
|
908
|
+
(archive) => filter(archive.owner, archive.lock)
|
|
909
|
+
)
|
|
910
|
+
)
|
|
911
|
+
);
|
|
912
|
+
}
|
|
913
|
+
function sumHoldings(holdings) {
|
|
914
|
+
if (holdings.length > 0) {
|
|
915
|
+
const instrumentId = holdings[0].instrumentId;
|
|
916
|
+
for (const holding of holdings) {
|
|
917
|
+
if (holding.instrumentId.admin !== instrumentId.admin || holding.instrumentId.id !== instrumentId.id) {
|
|
918
|
+
throw new Error(
|
|
919
|
+
`Attempted to call sumHoldings on heterogeneous instruments: ${JSON.stringify(instrumentId)} != ${JSON.stringify(holding.instrumentId)}`
|
|
920
|
+
);
|
|
921
|
+
}
|
|
922
|
+
}
|
|
923
|
+
}
|
|
924
|
+
return BigNumber__default.default.sum(
|
|
925
|
+
...holdings.map((h) => h.amount).concat(["0"])
|
|
926
|
+
// avoid NaN
|
|
927
|
+
);
|
|
928
|
+
}
|
|
929
|
+
function computeAmountChanges(children, meta, partyId) {
|
|
930
|
+
const burnAmount = BigNumber__default.default(getMetaKeyValue(BurnedMetaKey, meta) || "0");
|
|
931
|
+
const partyHoldingAmountChange = sumHoldingsChange(
|
|
932
|
+
children,
|
|
933
|
+
(owner) => owner === partyId
|
|
934
|
+
);
|
|
935
|
+
const otherPartiesHoldingAmountChange = sumHoldingsChange(
|
|
936
|
+
children,
|
|
937
|
+
(owner) => owner !== partyId
|
|
938
|
+
);
|
|
939
|
+
const mintAmount = partyHoldingAmountChange.plus(burnAmount).plus(otherPartiesHoldingAmountChange);
|
|
940
|
+
return {
|
|
941
|
+
burnAmount: burnAmount.toString(),
|
|
942
|
+
mintAmount: mintAmount.toString()
|
|
943
|
+
};
|
|
944
|
+
}
|
|
945
|
+
function computeSummary(instrumentId, changes, partyId) {
|
|
946
|
+
const amountChange = sumHoldingsChange(
|
|
947
|
+
changes,
|
|
948
|
+
(owner) => owner === partyId
|
|
949
|
+
);
|
|
950
|
+
const outputAmount = sumHoldings(changes.creates);
|
|
951
|
+
const inputAmount = sumHoldings(changes.archives);
|
|
952
|
+
return {
|
|
953
|
+
instrumentId,
|
|
954
|
+
amountChange: amountChange.toString(),
|
|
955
|
+
numOutputs: changes.creates.length,
|
|
956
|
+
outputAmount: outputAmount.toString(),
|
|
957
|
+
numInputs: changes.archives.length,
|
|
958
|
+
inputAmount: inputAmount.toString()
|
|
959
|
+
};
|
|
960
|
+
}
|
|
961
|
+
function holdingsChangeByInstrument(changes) {
|
|
962
|
+
const map = new InstrumentMap();
|
|
963
|
+
for (const create of changes.creates) {
|
|
964
|
+
if (map.has(create.instrumentId)) {
|
|
965
|
+
map.get(create.instrumentId).creates.push(create);
|
|
966
|
+
} else {
|
|
967
|
+
map.set(create.instrumentId, { creates: [create], archives: [] });
|
|
968
|
+
}
|
|
969
|
+
}
|
|
970
|
+
for (const archive of changes.archives) {
|
|
971
|
+
if (map.has(archive.instrumentId)) {
|
|
972
|
+
map.get(archive.instrumentId).archives.push(archive);
|
|
973
|
+
} else {
|
|
974
|
+
map.set(archive.instrumentId, { creates: [], archives: [archive] });
|
|
975
|
+
}
|
|
976
|
+
}
|
|
977
|
+
return map;
|
|
978
|
+
}
|
|
979
|
+
function computeSummaries(changes, partyId) {
|
|
980
|
+
const byInstrument = holdingsChangeByInstrument(changes);
|
|
981
|
+
return [...byInstrument.entries()].map(
|
|
982
|
+
([instrumentId, change]) => computeSummary(instrumentId, change, partyId)
|
|
983
|
+
);
|
|
984
|
+
}
|
|
985
|
+
function holdingChangesNonEmpty(event) {
|
|
986
|
+
return event.unlockedHoldingsChange.creates.length > 0 || event.unlockedHoldingsChange.archives.length > 0 || event.lockedHoldingsChange.creates.length > 0 || event.lockedHoldingsChange.archives.length > 0;
|
|
987
|
+
}
|
|
988
|
+
var emptyHoldingsChangeSummary = {
|
|
989
|
+
// This is obviously incorrect, but the field was introduced at the same
|
|
990
|
+
// time at which we introduced the more correct per-instrument summaries,
|
|
991
|
+
// so we know that old code couldn't use this (broken) field, and new code
|
|
992
|
+
// should use the correct summaries.
|
|
993
|
+
instrumentId: { admin: "", id: "" },
|
|
994
|
+
numInputs: 0,
|
|
995
|
+
numOutputs: 0,
|
|
996
|
+
inputAmount: "0",
|
|
997
|
+
outputAmount: "0",
|
|
998
|
+
amountChange: "0"
|
|
999
|
+
};
|
|
1000
|
+
|
|
1001
|
+
exports.AllKnownMetaKeys = AllKnownMetaKeys;
|
|
1002
|
+
exports.BurnedMetaKey = BurnedMetaKey;
|
|
1003
|
+
exports.ReasonMetaKey = ReasonMetaKey;
|
|
1004
|
+
exports.SenderMetaKey = SenderMetaKey;
|
|
1005
|
+
exports.TokenStandardTransactionInterfaces = TokenStandardTransactionInterfaces;
|
|
1006
|
+
exports.TransactionParser = TransactionParser;
|
|
1007
|
+
exports.TxKindMetaKey = TxKindMetaKey;
|
|
1008
|
+
exports.ensureInterfaceViewIsPresent = ensureInterfaceViewIsPresent;
|
|
1009
|
+
exports.getInterfaceView = getInterfaceView;
|
|
1010
|
+
exports.getKnownInterfaceView = getKnownInterfaceView;
|
|
1011
|
+
exports.getMetaKeyValue = getMetaKeyValue;
|
|
1012
|
+
exports.hasInterface = hasInterface;
|
|
1013
|
+
exports.matchInterfaceIds = matchInterfaceIds;
|
|
1014
|
+
exports.mergeMetas = mergeMetas;
|
|
1015
|
+
exports.removeParsedMetaKeys = removeParsedMetaKeys;
|
|
1016
|
+
exports.renderTransaction = renderTransaction;
|
|
1017
|
+
exports.splitInterfaceId = splitInterfaceId;
|
|
1018
|
+
//# sourceMappingURL=index.cjs.map
|
|
1019
|
+
//# sourceMappingURL=index.cjs.map
|