@canton-network/core-tx-visualizer 0.3.2 → 0.5.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/dist/Tx.test.js CHANGED
@@ -4,7 +4,7 @@ import { expect, test } from '@jest/globals';
4
4
  import { PreparedTransaction } from '@canton-network/core-ledger-proto';
5
5
  import * as path from 'path';
6
6
  import { readFileSync } from 'fs';
7
- import { decodePreparedTransaction } from '.';
7
+ import { decodePreparedTransaction, hashPreparedTransaction } from '.';
8
8
  import camelcaseKeys from 'camelcase-keys';
9
9
  test('decode a base 64 encoded prepared tx', async () => {
10
10
  const base64EncodedPreparedTx = 'Cp8GCgMyLjESATAa8AUKATDCPukFCuYFCgMyLjESQjAwNTUwODAyZGRiMTYzNzFmNWZjNmQzNjRlNmNkNGIzMjgzYTllYjVjMGNjYjEyMWFlMzY4Y2RlYmJhZDBmYmY1NhoOQWRtaW5Xb3JrZmxvd3MiXgpAMmEzOGI5NjNmNmFiZjQ1Yjc2YzcwMmY5NzAwYmZkOTA2MDU1NTg3MmFmOTE1ZWY3ZjhmNjg3OTVlMmM4MzFiZBIUQ2FudG9uLkludGVybmFsLlBpbmcaBFBpbmcqtgJyswIKXgpAMmEzOGI5NjNmNmFiZjQ1Yjc2YzcwMmY5NzAwYmZkOTA2MDU1NTg3MmFmOTE1ZWY3ZjhmNjg3OTVlMmM4MzFiZBIUQ2FudG9uLkludGVybmFsLlBpbmcaBFBpbmcSDwoCaWQSCUIHcGluZ19pZBJdCglpbml0aWF0b3ISUDpOb3BlcmF0b3I6OjEyMjBkNDRmYzFjM2JhMGI1YmRmN2I5NTZlZTcxYmM5NGViZTJkMjMyNThkYzI2OGZkZjA4MjRmYmFlZmYyYzYxNDI0EmEKCXJlc3BvbmRlchJUOlJwYXJ0aWNpcGFudDE6OjEyMjBkNDRmYzFjM2JhMGI1YmRmN2I5NTZlZTcxYmM5NGViZTJkMjMyNThkYzI2OGZkZjA4MjRmYmFlZmYyYzYxNDI0Mk5vcGVyYXRvcjo6MTIyMGQ0NGZjMWMzYmEwYjViZGY3Yjk1NmVlNzFiYzk0ZWJlMmQyMzI1OGRjMjY4ZmRmMDgyNGZiYWVmZjJjNjE0MjQ6Tm9wZXJhdG9yOjoxMjIwZDQ0ZmMxYzNiYTBiNWJkZjdiOTU2ZWU3MWJjOTRlYmUyZDIzMjU4ZGMyNjhmZGYwODI0ZmJhZWZmMmM2MTQyNDpScGFydGljaXBhbnQxOjoxMjIwZDQ0ZmMxYzNiYTBiNWJkZjdiOTU2ZWU3MWJjOTRlYmUyZDIzMjU4ZGMyNjhmZGYwODI0ZmJhZWZmMmM2MTQyNCIiEiBr2qJTURRRnXWp6y1EyXQiB69cfe50kJw0eYN1UF39nhL1ARJ2Ck5vcGVyYXRvcjo6MTIyMGQ0NGZjMWMzYmEwYjViZGY3Yjk1NmVlNzFiYzk0ZWJlMmQyMzI1OGRjMjY4ZmRmMDgyNGZiYWVmZjJjNjE0MjQSJGYyZWM0ZDhmLWNjYzEtNDAyYi1iMjc4LTc1NTZmZGQyYjQxMhpMd2FsbGV0OjoxMjIwZTdiMjNlYTUyZWI1YzY3MmZiMGIxY2RiYzkxNjkyMmZmZWQzZGQ3Njc2YzIyM2E2MDU2NjQzMTVlMmQ0M2VkZCokYTMyODE2MmUtNzI4ZS00ZTA1LWFjNzgtYjM0ZjA3MDk4M2JhMK7Y9/LU944D';
@@ -16,3 +16,9 @@ test('decode a base 64 encoded prepared tx', async () => {
16
16
  const message = PreparedTransaction.fromJson(camelCasePreparedTx);
17
17
  expect(message === preparedTx);
18
18
  });
19
+ test('hash from preparedTx ledger api call should match calculated hash', async () => {
20
+ const preparedTxFromLedgerAPi = 'f97Cv1BO7QS7jmSY03p56JGsPf60Vx/ABXmRub7iiQI=';
21
+ const preparedTx2 = 'CsoHCgMyLjESATAamwcKATDCPpQHCpEHCgMyLjESQjAwMTY4Nzc3ODEwNzU3MmJlZWVjYzQzODk3MmQxODQ4M2VhZDI1MGQxZDUwYmI2MzU3ZjdmYjhmNjdkY2U3ZDYzNRoNc3BsaWNlLXdhbGxldCKCAQpAZWI2ZTAxZWZhY2MzMzk3ZTIzYzZiZThiOWJlN2RiNGJmMzc2NzIyMTE5NzRkNjllMjRiNDg5ODBlMmY5OGI3ZRIhU3BsaWNlLldhbGxldC5UcmFuc2ZlclByZWFwcHJvdmFsGhtUcmFuc2ZlclByZWFwcHJvdmFsUHJvcG9zYWwqtQNysgMKggEKQGViNmUwMWVmYWNjMzM5N2UyM2M2YmU4YjliZTdkYjRiZjM3NjcyMjExOTc0ZDY5ZTI0YjQ4OTgwZTJmOThiN2USIVNwbGljZS5XYWxsZXQuVHJhbnNmZXJQcmVhcHByb3ZhbBobVHJhbnNmZXJQcmVhcHByb3ZhbFByb3Bvc2FsElcKCHJlY2VpdmVyEks6SWJvYjo6MTIyMDViZTNiOWQxNzc1NzNmZmZiNjhlYjI0NTk4NmY4OGI5ZGY1OGQ0NGNlNTc1ODE5MDc4OTcwNTgwZDg3ZDFkYzAScgoIcHJvdmlkZXISZjpkYXBwX3VzZXJfbG9jYWxuZXQtbG9jYWxwYXJ0eS0xOjoxMjIwM2E1MmZlNWFmM2I4N2UwNjk2MTgyYWM2NjhhNmNiMzE1ZGFiNGJkYzMwZGE5ZTViNmRkYTllYjcyODc4NDIxNhJeCgtleHBlY3RlZERzbxJPUk0KSzpJRFNPOjoxMjIwYmJkMDAwYjY5ODc1NzNiOGMwOWY0NDRlNGRmNTUwOWFmODk5N2I4MzkxMDlkN2UyYzIxMmQ1NDdmMGFmMDk1MDJJYm9iOjoxMjIwNWJlM2I5ZDE3NzU3M2ZmZmI2OGViMjQ1OTg2Zjg4YjlkZjU4ZDQ0Y2U1NzU4MTkwNzg5NzA1ODBkODdkMWRjMDpkYXBwX3VzZXJfbG9jYWxuZXQtbG9jYWxwYXJ0eS0xOjoxMjIwM2E1MmZlNWFmM2I4N2UwNjk2MTgyYWM2NjhhNmNiMzE1ZGFiNGJkYzMwZGE5ZTViNmRkYTllYjcyODc4NDIxNjpJYm9iOjoxMjIwNWJlM2I5ZDE3NzU3M2ZmZmI2OGViMjQ1OTg2Zjg4YjlkZjU4ZDQ0Y2U1NzU4MTkwNzg5NzA1ODBkODdkMWRjMCIiEiDBzeNcgqLvsssBxhNx7wP9pK71TsAprgz+a8jag/Lb3RL3ARJxCklib2I6OjEyMjA1YmUzYjlkMTc3NTczZmZmYjY4ZWIyNDU5ODZmODhiOWRmNThkNDRjZTU3NTgxOTA3ODk3MDU4MGQ4N2QxZGMwEiQ5NzU4ZTQ2ZS05ZmJlLTRmOTQtOTczZC04NWQ5ZTBmMTMyNzUaU2dsb2JhbC1kb21haW46OjEyMjBiYmQwMDBiNjk4NzU3M2I4YzA5ZjQ0NGU0ZGY1NTA5YWY4OTk3YjgzOTEwOWQ3ZTJjMjEyZDU0N2YwYWYwOTUwKiQ5NGJkYmFmNS0wYjJjLTQwYmMtOTZjZC1jM2M5YTlkODQ3ZDIw+eaGkdz0jwM=';
22
+ const hashResult = await hashPreparedTransaction(preparedTx2, 'base64');
23
+ expect(hashResult === preparedTxFromLedgerAPi);
24
+ });
@@ -1,4 +1,6 @@
1
1
  import { PreparedTransaction } from '@canton-network/core-ledger-proto';
2
2
  export declare function encodeString(value?: string): Promise<Uint8Array>;
3
3
  export declare function computePreparedTransaction(preparedTransaction: PreparedTransaction): Promise<Uint8Array>;
4
+ export declare function computeSha256CantonHash(purpose: number, bytes: Uint8Array): Promise<Uint8Array<ArrayBufferLike>>;
5
+ export declare function computeMultiHashForTopology(hashes: Uint8Array[]): Promise<Uint8Array<ArrayBufferLike>>;
4
6
  //# sourceMappingURL=hashing_scheme_v2.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"hashing_scheme_v2.d.ts","sourceRoot":"","sources":["../src/hashing_scheme_v2.ts"],"names":[],"mappings":"AAGA,OAAO,EAOH,mBAAmB,EACtB,MAAM,mCAAmC,CAAA;AA6C1C,wBAAsB,YAAY,CAAC,KAAK,GAAE,MAAW,GAAG,OAAO,CAAC,UAAU,CAAC,CAG1E;AAqbD,wBAAsB,0BAA0B,CAC5C,mBAAmB,EAAE,mBAAmB,GACzC,OAAO,CAAC,UAAU,CAAC,CAErB"}
1
+ {"version":3,"file":"hashing_scheme_v2.d.ts","sourceRoot":"","sources":["../src/hashing_scheme_v2.ts"],"names":[],"mappings":"AAGA,OAAO,EAOH,mBAAmB,EACtB,MAAM,mCAAmC,CAAA;AA8C1C,wBAAsB,YAAY,CAAC,KAAK,GAAE,MAAW,GAAG,OAAO,CAAC,UAAU,CAAC,CAG1E;AA4cD,wBAAsB,0BAA0B,CAC5C,mBAAmB,EAAE,mBAAmB,GACzC,OAAO,CAAC,UAAU,CAAC,CAErB;AAED,wBAAsB,uBAAuB,CACzC,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,UAAU,wCAQpB;AAED,wBAAsB,2BAA2B,CAAC,MAAM,EAAE,UAAU,EAAE,wCAerE"}
@@ -1,7 +1,7 @@
1
1
  // Copyright (c) 2025 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
2
2
  // SPDX-License-Identifier: Apache-2.0
3
3
  import { HashingSchemeVersion, } from '@canton-network/core-ledger-proto';
4
- import { mkByteArray, sha256 } from './utils.js';
4
+ import { mkByteArray, sha256, toHex } from './utils.js';
5
5
  // Hash purpose reserved for prepared transaction
6
6
  const PREPARED_TRANSACTION_HASH_PURPOSE = Uint8Array.from([
7
7
  0x00, 0x00, 0x00, 0x30,
@@ -68,16 +68,13 @@ async function encodeRepeated(values = [], encodeFn) {
68
68
  }
69
69
  function findSeed(nodeId, nodeSeeds) {
70
70
  const seed = nodeSeeds.find((seed) => seed.nodeId.toString() === nodeId)?.seed;
71
- if (!seed) {
72
- throw new Error(`Seed for node ID ${nodeId} not found`);
73
- }
74
71
  return seed;
75
72
  }
76
73
  async function encodeIdentifier(identifier) {
77
74
  return mkByteArray(await encodeString(identifier.packageId), await encodeRepeated(identifier.moduleName.split('.'), encodeString), await encodeRepeated(identifier.entityName.split('.'), encodeString));
78
75
  }
79
76
  async function encodeMetadata(metadata) {
80
- return mkByteArray(1, await encodeRepeated(metadata.submitterInfo?.actAs, encodeString), await encodeString(metadata.submitterInfo?.commandId), await encodeString(metadata.transactionUuid), await encodeInt32(metadata.mediatorGroup), await encodeString(metadata.synchronizerId), await encodeProtoOptional(metadata, 'minLedgerEffectiveTime', metadata.minLedgerEffectiveTime, encodeInt64), await encodeProtoOptional(metadata, 'maxLedgerEffectiveTime', metadata.maxLedgerEffectiveTime, encodeInt64), await encodeRepeated(metadata.inputContracts, encodeInputContract));
77
+ return mkByteArray(Uint8Array.from([0x01]), await encodeRepeated(metadata.submitterInfo?.actAs, encodeString), await encodeString(metadata.submitterInfo?.commandId), await encodeString(metadata.transactionUuid), await encodeInt32(metadata.mediatorGroup), await encodeString(metadata.synchronizerId), await encodeProtoOptional(metadata, 'minLedgerEffectiveTime', metadata.minLedgerEffectiveTime, encodeInt64), await encodeProtoOptional(metadata, 'maxLedgerEffectiveTime', metadata.maxLedgerEffectiveTime, encodeInt64), await encodeInt64(metadata.preparationTime), await encodeRepeated(metadata.inputContracts, encodeInputContract));
81
78
  }
82
79
  async function encodeCreateNode(create, nodeId, nodeSeeds) {
83
80
  return create
@@ -85,7 +82,7 @@ async function encodeCreateNode(create, nodeId, nodeSeeds) {
85
82
  : mkByteArray();
86
83
  }
87
84
  async function encodeExerciseNode(exercise, nodeId, nodesDict, nodeSeeds) {
88
- return mkByteArray(NODE_ENCODING_VERSION, await encodeString(exercise.lfVersion), 1 /** Exercise node tag */, await encodeHash(findSeed(nodeId, nodeSeeds)), await encodeHexString(exercise.contractId), await encodeString(exercise.packageName), await encodeIdentifier(exercise.templateId), await encodeRepeated(exercise.signatories, encodeString), await encodeRepeated(exercise.actingParties, encodeString), await encodeProtoOptional(exercise, 'interfaceId', exercise.interfaceId, encodeIdentifier), await encodeString(exercise.choiceId), await encodeValue(exercise.chosenValue), await encodeBool(exercise.consuming), await encodeProtoOptional(exercise, 'exerciseResult', exercise.exerciseResult, encodeValue), await encodeRepeated(exercise.choiceObservers, encodeString), await encodeRepeated(exercise.children, encodeNodeId(nodesDict, nodeSeeds)));
85
+ return mkByteArray(NODE_ENCODING_VERSION, await encodeString(exercise.lfVersion), 1 /** Exercise node tag */, await encodeHash(findSeed(nodeId, nodeSeeds)), await encodeHexString(exercise.contractId), await encodeString(exercise.packageName), await encodeIdentifier(exercise.templateId), await encodeRepeated(exercise.signatories, encodeString), await encodeRepeated(exercise.stakeholders, encodeString), await encodeRepeated(exercise.actingParties, encodeString), await encodeProtoOptional(exercise, 'interfaceId', exercise.interfaceId, encodeIdentifier), await encodeString(exercise.choiceId), await encodeValue(exercise.chosenValue), await encodeBool(exercise.consuming), await encodeProtoOptional(exercise, 'exerciseResult', exercise.exerciseResult, encodeValue), await encodeRepeated(exercise.choiceObservers, encodeString), await encodeRepeated(exercise.children, encodeNodeId(nodesDict, nodeSeeds)));
89
86
  }
90
87
  async function encodeFetchNode(fetch) {
91
88
  return mkByteArray(NODE_ENCODING_VERSION, await encodeString(fetch.lfVersion), 2 /** Fetch node tag */, await encodeHexString(fetch.contractId), await encodeString(fetch.packageName), await encodeIdentifier(fetch.templateId), await encodeRepeated(fetch.signatories, encodeString), await encodeRepeated(fetch.stakeholders, encodeString), await encodeProtoOptional(fetch, 'interfaceId', fetch.interfaceId, encodeIdentifier), await encodeRepeated(fetch.actingParties, encodeString));
@@ -104,49 +101,49 @@ async function encodeValue(value) {
104
101
  return Uint8Array.from([0]); // Unit value
105
102
  }
106
103
  else if (value.sum.oneofKind === 'bool') {
107
- return mkByteArray(0x01, await encodeBool(value.sum.bool));
104
+ return mkByteArray(Uint8Array.from([0x01]), await encodeBool(value.sum.bool));
108
105
  }
109
106
  else if (value.sum.oneofKind === 'int64') {
110
- return mkByteArray(0x02, await encodeInt64(parseInt(value.sum.int64)));
107
+ return mkByteArray(Uint8Array.from([0x02]), await encodeInt64(parseInt(value.sum.int64)));
111
108
  }
112
109
  else if (value.sum.oneofKind === 'numeric') {
113
- return mkByteArray(0x03, await encodeString(value.sum.numeric));
110
+ return mkByteArray(Uint8Array.from([0x03]), await encodeString(value.sum.numeric));
114
111
  }
115
112
  else if (value.sum.oneofKind === 'timestamp') {
116
- return mkByteArray(0x04, await encodeString(value.sum.timestamp));
113
+ return mkByteArray(Uint8Array.from([0x04]), await encodeInt64(BigInt(value.sum.timestamp)));
117
114
  }
118
115
  else if (value.sum.oneofKind === 'date') {
119
- return mkByteArray(0x05, await encodeInt32(value.sum.date));
116
+ return mkByteArray(Uint8Array.from([0x05]), await encodeInt32(value.sum.date));
120
117
  }
121
118
  else if (value.sum.oneofKind === 'party') {
122
- return mkByteArray(0x06, await encodeString(value.sum.party));
119
+ return mkByteArray(Uint8Array.from([0x06]), await encodeString(value.sum.party));
123
120
  }
124
121
  else if (value.sum.oneofKind === 'text') {
125
- return mkByteArray(0x07, await encodeString(value.sum.text));
122
+ return mkByteArray(Uint8Array.from([0x07]), await encodeString(value.sum.text));
126
123
  }
127
124
  else if (value.sum.oneofKind === 'contractId') {
128
- return mkByteArray(0x08, await encodeHexString(value.sum.contractId));
125
+ return mkByteArray(Uint8Array.from([0x08]), await encodeHexString(value.sum.contractId));
129
126
  }
130
127
  else if (value.sum.oneofKind === 'optional') {
131
- return mkByteArray(0x09, await encodeProtoOptional(value.sum.optional, 'value', value.sum.optional.value, encodeValue));
128
+ return mkByteArray(Uint8Array.from([0x09]), await encodeProtoOptional(value.sum.optional, 'value', value.sum.optional.value, encodeValue));
132
129
  }
133
130
  else if (value.sum.oneofKind === 'list') {
134
- return mkByteArray(0x0a, await encodeRepeated(value.sum.list.elements, encodeValue));
131
+ return mkByteArray(Uint8Array.from([0x0a]), await encodeRepeated(value.sum.list.elements, encodeValue));
135
132
  }
136
133
  else if (value.sum.oneofKind === 'textMap') {
137
- return mkByteArray(0x0b, await encodeRepeated(value.sum.textMap?.entries, encodeTextMapEntry));
134
+ return mkByteArray(Uint8Array.from([0x0b]), await encodeRepeated(value.sum.textMap?.entries, encodeTextMapEntry));
138
135
  }
139
136
  else if (value.sum.oneofKind === 'record') {
140
- return mkByteArray(0x0c, await encodeProtoOptional(value.sum.record, 'recordId', value.sum.record.recordId, encodeIdentifier), await encodeRepeated(value.sum.record.fields, encodeRecordField));
137
+ return mkByteArray(Uint8Array.from([0x0c]), await encodeProtoOptional(value.sum.record, 'recordId', value.sum.record.recordId, encodeIdentifier), await encodeRepeated(value.sum.record.fields, encodeRecordField));
141
138
  }
142
139
  else if (value.sum.oneofKind === 'variant') {
143
- return mkByteArray(0x0d, await encodeProtoOptional(value.sum.variant, 'variantId', value.sum.variant.variantId, encodeIdentifier), await encodeString(value.sum.variant.constructor), await encodeValue(value.sum.variant.value));
140
+ return mkByteArray(Uint8Array.from([0x0d]), await encodeProtoOptional(value.sum.variant, 'variantId', value.sum.variant.variantId, encodeIdentifier), await encodeString(value.sum.variant.constructor), await encodeValue(value.sum.variant.value));
144
141
  }
145
142
  else if (value.sum.oneofKind === 'enum') {
146
- return mkByteArray(0x0e, await encodeProtoOptional(value.sum.enum, 'enumId', value.sum.enum.enumId, encodeIdentifier), await encodeString(value.sum.enum.constructor));
143
+ return mkByteArray(Uint8Array.from([0x0e]), await encodeProtoOptional(value.sum.enum, 'enumId', value.sum.enum.enumId, encodeIdentifier), await encodeString(value.sum.enum.constructor));
147
144
  }
148
145
  else if (value.sum.oneofKind === 'genMap') {
149
- return mkByteArray(0x0f, await encodeRepeated(value.sum.genMap?.entries, encodeGenMapEntry));
146
+ return mkByteArray(Uint8Array.from([0x0f]), await encodeRepeated(value.sum.genMap?.entries, encodeGenMapEntry));
150
147
  }
151
148
  throw new Error('Unsupported value type: ' + JSON.stringify(value));
152
149
  }
@@ -218,3 +215,22 @@ async function encodePreparedTransaction(preparedTransaction) {
218
215
  export async function computePreparedTransaction(preparedTransaction) {
219
216
  return sha256(await encodePreparedTransaction(preparedTransaction));
220
217
  }
218
+ export async function computeSha256CantonHash(purpose, bytes) {
219
+ const encodedPurpose = await encodeInt32(purpose);
220
+ const hashInput = await mkByteArray(encodedPurpose, bytes);
221
+ const hashBytes = await sha256(hashInput);
222
+ const multiprefix = new Uint8Array([0x12, 0x20]);
223
+ return mkByteArray(multiprefix, hashBytes);
224
+ }
225
+ export async function computeMultiHashForTopology(hashes) {
226
+ const sortedHashes = hashes
227
+ .slice()
228
+ .sort((a, b) => toHex(a).localeCompare(toHex(b)));
229
+ const numHashesBytes = await encodeInt32(sortedHashes.length);
230
+ const concatenatedHashes = [numHashesBytes];
231
+ for (const h of sortedHashes) {
232
+ const lengthBytes = await encodeInt32(h.length);
233
+ concatenatedHashes.push(lengthBytes, h);
234
+ }
235
+ return mkByteArray(...concatenatedHashes);
236
+ }
package/dist/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import { PreparedTransaction } from '@canton-network/core-ledger-proto';
2
+ export { computeSha256CantonHash, computeMultiHashForTopology, } from './hashing_scheme_v2.js';
2
3
  /**
3
4
  * Decodes a base64 encoded prepared transaction into a well-typed data model, generated directly from Protobuf definitions.
4
5
  *
@@ -19,5 +20,4 @@ type ValidationResult = Record<string, {
19
20
  locations: string[];
20
21
  }>;
21
22
  export declare const validateAuthorizedPartyIds: (preparedTransaction: string | PreparedTransaction, authorizedPartyIds: string[]) => ValidationResult;
22
- export {};
23
23
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,mBAAmB,EAAE,MAAM,mCAAmC,CAAA;AAIvE;;;;;GAKG;AACH,eAAO,MAAM,yBAAyB,GAClC,qBAAqB,MAAM,KAC5B,mBAGF,CAAA;AAED;;;;;;GAMG;AACH,eAAO,MAAM,uBAAuB,GAChC,qBAAqB,MAAM,GAAG,mBAAmB,EACjD,SAAQ,QAAQ,GAAG,KAAgB,KACpC,OAAO,CAAC,MAAM,CAiBhB,CAAA;AAED,KAAK,gBAAgB,GAAG,MAAM,CAC1B,MAAM,EACN;IACI,YAAY,EAAE,OAAO,CAAA;IACrB,SAAS,EAAE,MAAM,EAAE,CAAA;CACtB,CACJ,CAAA;AAED,eAAO,MAAM,0BAA0B,GACnC,qBAAqB,MAAM,GAAG,mBAAmB,EACjD,oBAAoB,MAAM,EAAE,KAC7B,gBAgEF,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,mBAAmB,EAAE,MAAM,mCAAmC,CAAA;AAGvE,OAAO,EACH,uBAAuB,EACvB,2BAA2B,GAC9B,MAAM,wBAAwB,CAAA;AAE/B;;;;;GAKG;AACH,eAAO,MAAM,yBAAyB,GAClC,qBAAqB,MAAM,KAC5B,mBAGF,CAAA;AAED;;;;;;GAMG;AACH,eAAO,MAAM,uBAAuB,GAChC,qBAAqB,MAAM,GAAG,mBAAmB,EACjD,SAAQ,QAAQ,GAAG,KAAgB,KACpC,OAAO,CAAC,MAAM,CAiBhB,CAAA;AAED,KAAK,gBAAgB,GAAG,MAAM,CAC1B,MAAM,EACN;IACI,YAAY,EAAE,OAAO,CAAA;IACrB,SAAS,EAAE,MAAM,EAAE,CAAA;CACtB,CACJ,CAAA;AAED,eAAO,MAAM,0BAA0B,GACnC,qBAAqB,MAAM,GAAG,mBAAmB,EACjD,oBAAoB,MAAM,EAAE,KAC7B,gBAgEF,CAAA"}
package/dist/index.js CHANGED
@@ -3,6 +3,7 @@
3
3
  import { PreparedTransaction } from '@canton-network/core-ledger-proto';
4
4
  import { computePreparedTransaction } from './hashing_scheme_v2.js';
5
5
  import { fromBase64, toBase64, toHex } from './utils.js';
6
+ export { computeSha256CantonHash, computeMultiHashForTopology, } from './hashing_scheme_v2.js';
6
7
  /**
7
8
  * Decodes a base64 encoded prepared transaction into a well-typed data model, generated directly from Protobuf definitions.
8
9
  *
package/dist/utils.d.ts CHANGED
@@ -4,6 +4,7 @@ export declare function fromBase64(b64: string): Uint8Array;
4
4
  export declare function toBase64(data: Uint8Array): string;
5
5
  /** Take a byte buffer (Uint8Array) and encode it into a hex string */
6
6
  export declare function toHex(bytes: Uint8Array): string;
7
+ export declare function fromHex(hex: string): Uint8Array;
7
8
  export declare function sha256(message: string | Uint8Array): Promise<Uint8Array>;
8
9
  /** Utility to concatenate byte arrays or single bytes */
9
10
  export declare function mkByteArray(...args: (number | Uint8Array)[]): Promise<Uint8Array>;
@@ -1 +1 @@
1
- {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAGA,gFAAgF;AAChF,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,CAQlD;AAED,yEAAyE;AACzE,wBAAgB,QAAQ,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,CAOjD;AAED,sEAAsE;AACtE,wBAAgB,KAAK,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAI/C;AAED,wBAAsB,MAAM,CACxB,OAAO,EAAE,MAAM,GAAG,UAAU,GAC7B,OAAO,CAAC,UAAU,CAAC,CASrB;AAED,yDAAyD;AACzD,wBAAsB,WAAW,CAC7B,GAAG,IAAI,EAAE,CAAC,MAAM,GAAG,UAAU,CAAC,EAAE,GACjC,OAAO,CAAC,UAAU,CAAC,CAuBrB"}
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAGA,gFAAgF;AAChF,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,CAQlD;AAED,yEAAyE;AACzE,wBAAgB,QAAQ,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,CAOjD;AAED,sEAAsE;AACtE,wBAAgB,KAAK,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAI/C;AAED,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,CAU/C;AAED,wBAAsB,MAAM,CACxB,OAAO,EAAE,MAAM,GAAG,UAAU,GAC7B,OAAO,CAAC,UAAU,CAAC,CASrB;AAED,yDAAyD;AACzD,wBAAsB,WAAW,CAC7B,GAAG,IAAI,EAAE,CAAC,MAAM,GAAG,UAAU,CAAC,EAAE,GACjC,OAAO,CAAC,UAAU,CAAC,CAuBrB"}
package/dist/utils.js CHANGED
@@ -25,6 +25,16 @@ export function toHex(bytes) {
25
25
  .map((byte) => byte.toString(16).padStart(2, '0'))
26
26
  .join('');
27
27
  }
28
+ export function fromHex(hex) {
29
+ if (hex.length % 2 !== 0) {
30
+ throw new Error('Invalid hex string length');
31
+ }
32
+ const bytes = new Uint8Array(hex.length / 2);
33
+ for (let i = 0; i < hex.length; i += 2) {
34
+ bytes[i / 2] = parseInt(hex.slice(i, i + 2), 16);
35
+ }
36
+ return bytes;
37
+ }
28
38
  export async function sha256(message) {
29
39
  const msg = typeof message === 'string'
30
40
  ? new TextEncoder().encode(message)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@canton-network/core-tx-visualizer",
3
- "version": "0.3.2",
3
+ "version": "0.5.0",
4
4
  "type": "module",
5
5
  "description": "Decode and visualize prepared transactions from Canton",
6
6
  "repository": "github:hyperledger-labs/splice-wallet-kernel",
@@ -25,7 +25,7 @@
25
25
  "typescript": "^5.8.3"
26
26
  },
27
27
  "dependencies": {
28
- "@canton-network/core-ledger-proto": "^0.4.0",
28
+ "@canton-network/core-ledger-proto": "^0.6.0",
29
29
  "@protobuf-ts/runtime": "^2.11.1",
30
30
  "@protobuf-ts/runtime-rpc": "^2.11.1",
31
31
  "@swc/core": "^1.13.3",