@ledgerhq/coin-canton 0.9.0-nightly.1 → 0.9.0-nightly.20251030160608

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (205) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/.unimportedrc.json +2 -1
  3. package/CHANGELOG.md +26 -9
  4. package/README.md +75 -0
  5. package/lib/bridge/deviceTransactionConfig.d.ts +1 -1
  6. package/lib/bridge/deviceTransactionConfig.d.ts.map +1 -1
  7. package/lib/bridge/deviceTransactionConfig.js +1 -1
  8. package/lib/bridge/deviceTransactionConfig.js.map +1 -1
  9. package/lib/bridge/estimateMaxSpendable.d.ts +2 -2
  10. package/lib/bridge/estimateMaxSpendable.d.ts.map +1 -1
  11. package/lib/bridge/estimateMaxSpendable.js +2 -3
  12. package/lib/bridge/estimateMaxSpendable.js.map +1 -1
  13. package/lib/bridge/getTransactionStatus.d.ts +5 -3
  14. package/lib/bridge/getTransactionStatus.d.ts.map +1 -1
  15. package/lib/bridge/getTransactionStatus.js +27 -10
  16. package/lib/bridge/getTransactionStatus.js.map +1 -1
  17. package/lib/bridge/index.d.ts +2 -2
  18. package/lib/bridge/index.d.ts.map +1 -1
  19. package/lib/bridge/index.js +3 -3
  20. package/lib/bridge/index.js.map +1 -1
  21. package/lib/bridge/onboard.d.ts.map +1 -1
  22. package/lib/bridge/onboard.js +48 -22
  23. package/lib/bridge/onboard.js.map +1 -1
  24. package/lib/bridge/prepareTransaction.js +1 -1
  25. package/lib/bridge/prepareTransaction.js.map +1 -1
  26. package/lib/bridge/serialization.d.ts +4 -0
  27. package/lib/bridge/serialization.d.ts.map +1 -0
  28. package/lib/bridge/serialization.js +36 -0
  29. package/lib/bridge/serialization.js.map +1 -0
  30. package/lib/bridge/signOperation.d.ts.map +1 -1
  31. package/lib/bridge/signOperation.js +11 -4
  32. package/lib/bridge/signOperation.js.map +1 -1
  33. package/lib/bridge/sync.d.ts.map +1 -1
  34. package/lib/bridge/sync.js +14 -6
  35. package/lib/bridge/sync.js.map +1 -1
  36. package/lib/bridge/transaction.js +1 -1
  37. package/lib/bridge/transaction.js.map +1 -1
  38. package/lib/common-logic/account/getBalance.d.ts +5 -1
  39. package/lib/common-logic/account/getBalance.d.ts.map +1 -1
  40. package/lib/common-logic/account/getBalance.js +2 -0
  41. package/lib/common-logic/account/getBalance.js.map +1 -1
  42. package/lib/common-logic/index.d.ts +1 -0
  43. package/lib/common-logic/index.d.ts.map +1 -1
  44. package/lib/common-logic/index.js +3 -1
  45. package/lib/common-logic/index.js.map +1 -1
  46. package/lib/common-logic/transaction/craftTransaction.js +1 -1
  47. package/lib/common-logic/transaction/craftTransaction.js.map +1 -1
  48. package/lib/common-logic/transaction/estimateFees.js +1 -1
  49. package/lib/common-logic/transaction/estimateFees.js.map +1 -1
  50. package/lib/common-logic/transaction/sign.d.ts +8 -0
  51. package/lib/common-logic/transaction/sign.d.ts.map +1 -0
  52. package/lib/common-logic/transaction/sign.js +45 -0
  53. package/lib/common-logic/transaction/sign.js.map +1 -0
  54. package/lib/common-logic/transaction/split.d.ts +9 -0
  55. package/lib/common-logic/transaction/split.d.ts.map +1 -0
  56. package/lib/common-logic/transaction/split.js +119 -0
  57. package/lib/common-logic/transaction/split.js.map +1 -0
  58. package/lib/common-logic/utils.js +2 -2
  59. package/lib/common-logic/utils.js.map +1 -1
  60. package/lib/network/gateway.d.ts +6 -1
  61. package/lib/network/gateway.d.ts.map +1 -1
  62. package/lib/network/gateway.js +6 -9
  63. package/lib/network/gateway.js.map +1 -1
  64. package/lib/test/cantonTestUtils.d.ts +4 -9
  65. package/lib/test/cantonTestUtils.d.ts.map +1 -1
  66. package/lib/test/cantonTestUtils.js +736 -27
  67. package/lib/test/cantonTestUtils.js.map +1 -1
  68. package/lib/test/fixtures.d.ts +5 -0
  69. package/lib/test/fixtures.d.ts.map +1 -0
  70. package/lib/test/fixtures.js +57 -0
  71. package/lib/test/fixtures.js.map +1 -0
  72. package/lib/types/bridge.d.ts +14 -2
  73. package/lib/types/bridge.d.ts.map +1 -1
  74. package/lib/types/errors.d.ts +6 -0
  75. package/lib/types/errors.d.ts.map +1 -1
  76. package/lib/types/errors.js +3 -1
  77. package/lib/types/errors.js.map +1 -1
  78. package/lib/types/index.d.ts +1 -0
  79. package/lib/types/index.d.ts.map +1 -1
  80. package/lib/types/index.js +1 -0
  81. package/lib/types/index.js.map +1 -1
  82. package/lib/types/signer.d.ts +15 -2
  83. package/lib/types/signer.d.ts.map +1 -1
  84. package/lib/types/transaction-proto.json +1238 -0
  85. package/lib-es/bridge/deviceTransactionConfig.d.ts +1 -1
  86. package/lib-es/bridge/deviceTransactionConfig.d.ts.map +1 -1
  87. package/lib-es/bridge/deviceTransactionConfig.js +1 -1
  88. package/lib-es/bridge/deviceTransactionConfig.js.map +1 -1
  89. package/lib-es/bridge/estimateMaxSpendable.d.ts +2 -2
  90. package/lib-es/bridge/estimateMaxSpendable.d.ts.map +1 -1
  91. package/lib-es/bridge/estimateMaxSpendable.js +2 -3
  92. package/lib-es/bridge/estimateMaxSpendable.js.map +1 -1
  93. package/lib-es/bridge/getTransactionStatus.d.ts +5 -3
  94. package/lib-es/bridge/getTransactionStatus.d.ts.map +1 -1
  95. package/lib-es/bridge/getTransactionStatus.js +27 -10
  96. package/lib-es/bridge/getTransactionStatus.js.map +1 -1
  97. package/lib-es/bridge/index.d.ts +2 -2
  98. package/lib-es/bridge/index.d.ts.map +1 -1
  99. package/lib-es/bridge/index.js +3 -3
  100. package/lib-es/bridge/index.js.map +1 -1
  101. package/lib-es/bridge/onboard.d.ts.map +1 -1
  102. package/lib-es/bridge/onboard.js +49 -23
  103. package/lib-es/bridge/onboard.js.map +1 -1
  104. package/lib-es/bridge/prepareTransaction.js +1 -1
  105. package/lib-es/bridge/prepareTransaction.js.map +1 -1
  106. package/lib-es/bridge/serialization.d.ts +4 -0
  107. package/lib-es/bridge/serialization.d.ts.map +1 -0
  108. package/lib-es/bridge/serialization.js +32 -0
  109. package/lib-es/bridge/serialization.js.map +1 -0
  110. package/lib-es/bridge/signOperation.d.ts.map +1 -1
  111. package/lib-es/bridge/signOperation.js +11 -4
  112. package/lib-es/bridge/signOperation.js.map +1 -1
  113. package/lib-es/bridge/sync.d.ts.map +1 -1
  114. package/lib-es/bridge/sync.js +14 -6
  115. package/lib-es/bridge/sync.js.map +1 -1
  116. package/lib-es/bridge/transaction.js +1 -1
  117. package/lib-es/bridge/transaction.js.map +1 -1
  118. package/lib-es/common-logic/account/getBalance.d.ts +5 -1
  119. package/lib-es/common-logic/account/getBalance.d.ts.map +1 -1
  120. package/lib-es/common-logic/account/getBalance.js +2 -0
  121. package/lib-es/common-logic/account/getBalance.js.map +1 -1
  122. package/lib-es/common-logic/index.d.ts +1 -0
  123. package/lib-es/common-logic/index.d.ts.map +1 -1
  124. package/lib-es/common-logic/index.js +1 -0
  125. package/lib-es/common-logic/index.js.map +1 -1
  126. package/lib-es/common-logic/transaction/craftTransaction.js +1 -1
  127. package/lib-es/common-logic/transaction/craftTransaction.js.map +1 -1
  128. package/lib-es/common-logic/transaction/estimateFees.js +1 -1
  129. package/lib-es/common-logic/transaction/estimateFees.js.map +1 -1
  130. package/lib-es/common-logic/transaction/sign.d.ts +8 -0
  131. package/lib-es/common-logic/transaction/sign.d.ts.map +1 -0
  132. package/lib-es/common-logic/transaction/sign.js +42 -0
  133. package/lib-es/common-logic/transaction/sign.js.map +1 -0
  134. package/lib-es/common-logic/transaction/split.d.ts +9 -0
  135. package/lib-es/common-logic/transaction/split.d.ts.map +1 -0
  136. package/lib-es/common-logic/transaction/split.js +83 -0
  137. package/lib-es/common-logic/transaction/split.js.map +1 -0
  138. package/lib-es/common-logic/utils.js +2 -2
  139. package/lib-es/common-logic/utils.js.map +1 -1
  140. package/lib-es/network/gateway.d.ts +6 -1
  141. package/lib-es/network/gateway.d.ts.map +1 -1
  142. package/lib-es/network/gateway.js +5 -10
  143. package/lib-es/network/gateway.js.map +1 -1
  144. package/lib-es/test/cantonTestUtils.d.ts +4 -9
  145. package/lib-es/test/cantonTestUtils.d.ts.map +1 -1
  146. package/lib-es/test/cantonTestUtils.js +697 -21
  147. package/lib-es/test/cantonTestUtils.js.map +1 -1
  148. package/lib-es/test/fixtures.d.ts +5 -0
  149. package/lib-es/test/fixtures.d.ts.map +1 -0
  150. package/lib-es/test/fixtures.js +49 -0
  151. package/lib-es/test/fixtures.js.map +1 -0
  152. package/lib-es/types/bridge.d.ts +14 -2
  153. package/lib-es/types/bridge.d.ts.map +1 -1
  154. package/lib-es/types/errors.d.ts +6 -0
  155. package/lib-es/types/errors.d.ts.map +1 -1
  156. package/lib-es/types/errors.js +2 -0
  157. package/lib-es/types/errors.js.map +1 -1
  158. package/lib-es/types/index.d.ts +1 -0
  159. package/lib-es/types/index.d.ts.map +1 -1
  160. package/lib-es/types/index.js +1 -0
  161. package/lib-es/types/index.js.map +1 -1
  162. package/lib-es/types/signer.d.ts +15 -2
  163. package/lib-es/types/signer.d.ts.map +1 -1
  164. package/lib-es/types/transaction-proto.json +1238 -0
  165. package/package.json +13 -10
  166. package/scripts/generate.js +261 -0
  167. package/src/bridge/deviceTransactionConfig.test.ts +14 -10
  168. package/src/bridge/deviceTransactionConfig.ts +2 -2
  169. package/src/bridge/estimateMaxSpendable.ts +6 -8
  170. package/src/bridge/getTransactionStatus.test.ts +103 -165
  171. package/src/bridge/getTransactionStatus.ts +43 -11
  172. package/src/bridge/index.ts +6 -5
  173. package/src/bridge/onboard.integ.test.ts +8 -51
  174. package/src/bridge/onboard.ts +58 -33
  175. package/src/bridge/prepareTransaction.ts +1 -1
  176. package/src/bridge/serialization.ts +44 -0
  177. package/src/bridge/signOperation.test.ts +123 -0
  178. package/src/bridge/signOperation.ts +13 -6
  179. package/src/bridge/sync.integ.test.ts +157 -132
  180. package/src/bridge/sync.test.ts +5 -1
  181. package/src/bridge/sync.ts +18 -7
  182. package/src/bridge/transaction.ts +1 -1
  183. package/src/common-logic/account/getBalance.ts +12 -2
  184. package/src/common-logic/account/getBalance.unit.test.ts +7 -1
  185. package/src/common-logic/index.ts +1 -0
  186. package/src/common-logic/transaction/craftTransaction.ts +1 -1
  187. package/src/common-logic/transaction/estimateFees.test.ts +10 -0
  188. package/src/common-logic/transaction/estimateFees.ts +1 -1
  189. package/src/common-logic/transaction/sign.test.ts +389 -0
  190. package/src/common-logic/transaction/sign.ts +59 -0
  191. package/src/common-logic/transaction/split.test.ts +50 -0
  192. package/src/common-logic/transaction/split.ts +101 -0
  193. package/src/common-logic/utils.test.ts +22 -30
  194. package/src/common-logic/utils.ts +2 -2
  195. package/src/network/gateway.integ.test.ts +5 -6
  196. package/src/network/gateway.ts +13 -10
  197. package/src/test/cantonTestUtils.ts +789 -24
  198. package/src/test/fixtures.ts +53 -0
  199. package/src/test/prepare-transfer-serialized.json +26 -0
  200. package/src/test/prepare-transfer.json +3298 -0
  201. package/src/types/bridge.ts +15 -2
  202. package/src/types/errors.ts +3 -0
  203. package/src/types/index.ts +1 -0
  204. package/src/types/signer.ts +21 -3
  205. package/src/types/transaction-proto.json +1238 -0
@@ -0,0 +1,50 @@
1
+ import prepareTransferMockSerialized from "../../test/prepare-transfer-serialized.json";
2
+ import prepareTransferMock from "../../test/prepare-transfer.json";
3
+ import { splitTransaction } from "./split";
4
+
5
+ function uint8ArrayToHex(bytes: Uint8Array): string {
6
+ return Array.from(bytes, b => b.toString(16).padStart(2, "0")).join("");
7
+ }
8
+
9
+ describe("splitTransaction", () => {
10
+ it("should split transaction correctly", () => {
11
+ const transactionData = prepareTransferMock;
12
+ const result = splitTransaction(transactionData);
13
+
14
+ expect(result).toBeDefined();
15
+ expect(result.damlTransaction).toBeInstanceOf(Uint8Array);
16
+ expect(result.nodes).toBeInstanceOf(Array);
17
+ expect(result.metadata).toBeInstanceOf(Uint8Array);
18
+ expect(result.inputContracts).toBeInstanceOf(Array);
19
+ });
20
+
21
+ it("should properly serialize damlTransaction", () => {
22
+ const transactionData = prepareTransferMock;
23
+ const { damlTransaction } = splitTransaction(transactionData);
24
+
25
+ expect(uint8ArrayToHex(damlTransaction)).toEqual(prepareTransferMockSerialized.damlTransaction);
26
+ });
27
+
28
+ it("should properly serialize nodes", () => {
29
+ const transactionData = prepareTransferMock;
30
+ const { nodes } = splitTransaction(transactionData);
31
+
32
+ expect(nodes.map(uint8ArrayToHex)).toEqual(prepareTransferMockSerialized.nodes);
33
+ });
34
+
35
+ it("should properly serialize metadata", () => {
36
+ const transactionData = prepareTransferMock;
37
+ const { metadata } = splitTransaction(transactionData);
38
+
39
+ expect(uint8ArrayToHex(metadata)).toEqual(prepareTransferMockSerialized.metadata);
40
+ });
41
+
42
+ it("should properly serialize inputContracts", () => {
43
+ const transactionData = prepareTransferMock;
44
+ const { inputContracts } = splitTransaction(transactionData);
45
+
46
+ expect(inputContracts.map(uint8ArrayToHex)).toEqual(
47
+ prepareTransferMockSerialized.inputContracts,
48
+ );
49
+ });
50
+ });
@@ -0,0 +1,101 @@
1
+ import * as protobuf from "protobufjs";
2
+ import { PrepareTransferResponse } from "../../network/gateway";
3
+ import { CantonPreparedTransaction } from "../../types/signer";
4
+ import * as transactionProto from "../../types/transaction-proto.json";
5
+
6
+ const root: { [key: string]: any } = protobuf.Root.fromJSON(transactionProto) || {};
7
+
8
+ const RESERVED_WORDS = {
9
+ bool: "bool_",
10
+ enum: "enum_",
11
+ constructor: "constructor_",
12
+ };
13
+
14
+ const replaceReservedWords = (obj: any): any => {
15
+ if (obj === null || typeof obj !== "object") return obj;
16
+ if (Array.isArray(obj)) return obj.map(replaceReservedWords);
17
+
18
+ const transformed: any = {};
19
+ for (const [key, value] of Object.entries(obj)) {
20
+ transformed[RESERVED_WORDS[key as keyof typeof RESERVED_WORDS] || key] =
21
+ replaceReservedWords(value);
22
+ }
23
+ return transformed;
24
+ };
25
+
26
+ /**
27
+ * Splits a Canton transaction into components for prepared transaction signing.
28
+ * Converts protobuf transaction data into structured components that can be
29
+ * sent to the Ledger device for signing.
30
+ */
31
+ export function splitTransaction(
32
+ transaction: PrepareTransferResponse["json"],
33
+ ): CantonPreparedTransaction {
34
+ const { transaction: transactionData, metadata } = transaction;
35
+
36
+ // Process DAML transaction
37
+ const DeviceDamlTransaction = root.lookupType(
38
+ "com.daml.ledger.api.v2.interactive.DeviceDamlTransaction",
39
+ );
40
+
41
+ const damlTransactionBytes = DeviceDamlTransaction.encode({
42
+ version: transactionData.version,
43
+ roots: transactionData.roots,
44
+ nodesCount: transactionData.nodes?.length || 0,
45
+ nodeSeeds: (transactionData.nodeSeeds || []).map((seed: any) => ({
46
+ seed: Uint8Array.from(Buffer.from(seed.seed, "base64")),
47
+ ...(seed.nodeId && seed.nodeId !== 0 && { nodeId: seed.nodeId }),
48
+ })),
49
+ }).finish();
50
+
51
+ // Process input contracts
52
+ const inputContracts = (metadata.inputContracts || []).map((contract: any) => {
53
+ const { eventBlob, ...contractWithoutBlob } = contract;
54
+ const InputContract = root.lookupType(
55
+ "com.daml.ledger.api.v2.interactive.DeviceMetadata.InputContract",
56
+ );
57
+ const contractPb = InputContract.fromObject(replaceReservedWords(contractWithoutBlob));
58
+ return InputContract.encode(contractPb).finish();
59
+ });
60
+
61
+ // Process metadata
62
+ const metadataData = {
63
+ submitterInfo: {
64
+ actAs: metadata.submitterInfo.actAs,
65
+ commandId: metadata.submitterInfo.commandId,
66
+ },
67
+ synchronizerId: metadata.synchronizerId,
68
+ ...(metadata.mediatorGroup !== undefined && { mediatorGroup: metadata.mediatorGroup }),
69
+ transactionUuid: metadata.transactionUuid,
70
+ submissionTime: Number.parseInt(metadata.preparationTime, 10),
71
+ inputContractsCount: metadata.inputContracts?.length || 0,
72
+ ...(metadata.minLedgerEffectiveTime && {
73
+ minLedgerEffectiveTime: Number.parseInt(metadata.minLedgerEffectiveTime, 10),
74
+ }),
75
+ ...(metadata.maxLedgerEffectiveTime && {
76
+ maxLedgerEffectiveTime: Number.parseInt(metadata.maxLedgerEffectiveTime, 10),
77
+ }),
78
+ };
79
+
80
+ const DeviceMetadata = root.lookupType("com.daml.ledger.api.v2.interactive.DeviceMetadata");
81
+ const metadataBytes = DeviceMetadata.encode(metadataData).finish();
82
+
83
+ // Process nodes
84
+ const nodesArray = transactionData.nodes || [];
85
+ const nodes = new Array(nodesArray.length);
86
+
87
+ for (const node of nodesArray) {
88
+ const nodeId = Number.parseInt(node.nodeId || "0", 10);
89
+ const Node = root.lookupType("com.daml.ledger.api.v2.interactive.DeviceDamlTransaction.Node");
90
+ const nodePb = Node.fromObject(replaceReservedWords(node));
91
+ const pos = nodesArray.length - 1 - nodeId;
92
+ nodes[pos] = Node.encode(nodePb).finish();
93
+ }
94
+
95
+ return {
96
+ damlTransaction: damlTransactionBytes,
97
+ nodes,
98
+ metadata: metadataBytes,
99
+ inputContracts,
100
+ };
101
+ }
@@ -5,18 +5,9 @@ describe("utils", () => {
5
5
  describe("isRecipientValid", () => {
6
6
  it("should return true for valid Canton addresses", () => {
7
7
  const validAddresses = [
8
- "abc::123",
9
- "hello::1",
10
- "test123::456",
11
- "a::0",
12
- "party::999",
13
- "user123::42",
14
- "canton_1a2b3c4d5e6f7g8h9i0j1k2l3m4n5o6p7q8r9s0t1u2v3w4x5y6z::123",
15
- "test::123456789",
16
- "abc::abc", // letters after ::
17
- "test::ABC123", // mixed case letters and numbers
18
- "user::a1b2c3", // alphanumeric after ::
19
- "contract::XyZ789", // mixed case with numbers
8
+ "ldg::1220691e945dc1b210f3b6be9fbad73efaf642bfb96022552f66c9e2b83b00cb20e8",
9
+ "ldg-with-dash::1220691e945dc1b210f3b6be9fbad73efaf642bfb96022552f66c9e2b83b00cb20e8",
10
+ "ldg-with-number-1::1220691e945dc1b210f3b6be9fbad73efaf642bfb96022552f66c9e2b83b00cb20e8",
20
11
  ];
21
12
 
22
13
  validAddresses.forEach(address => {
@@ -26,6 +17,8 @@ describe("utils", () => {
26
17
 
27
18
  it("should return false for invalid Canton addresses", () => {
28
19
  const invalidAddresses = [
20
+ "ldg::1220691e945dc1b210f3b6be9fbad73efaf642bfb96022552f66c9e2b83b00cb20e", // too short fingerprint
21
+ "ldg::1220691e945dc1b210f3b6be9fbad73efaf642bfb96022552f66c9e2b83b00cb20e80", // too long fingerprint
29
22
  "", // empty string
30
23
  "::123", // no characters before ::
31
24
  "abc::", // no characters after ::
@@ -53,26 +46,25 @@ describe("utils", () => {
53
46
  });
54
47
 
55
48
  it("should handle edge cases", () => {
56
- expect(isRecipientValid("a::1")).toBe(true); // minimum valid case with number
57
- expect(isRecipientValid("a::a")).toBe(true); // minimum valid case with letter
58
- expect(isRecipientValid("1::1")).toBe(true); // number before ::
59
- expect(isRecipientValid("1::a")).toBe(true); // number before ::, letter after
60
- expect(isRecipientValid("_::1")).toBe(true); // underscore before ::
61
- expect(isRecipientValid("_::a")).toBe(true); // underscore before ::, letter after
62
- expect(isRecipientValid("-::1")).toBe(true); // dash before ::
63
- expect(isRecipientValid("-::a")).toBe(true); // dash before ::, letter after
64
- expect(isRecipientValid(".::1")).toBe(true); // dot before ::
65
- expect(isRecipientValid(".::a")).toBe(true); // dot before ::, letter after
49
+ const validHex68 = "1220691e945dc1b210f3b6be9fbad73efaf642bfb96022552f66c9e2b83b00cb20e8";
50
+ expect(isRecipientValid(`a::${validHex68}`)).toBe(true); // single letter prefix
51
+ expect(isRecipientValid(`1::${validHex68}`)).toBe(true); // single number prefix
52
+ expect(isRecipientValid(`a-1::${validHex68}`)).toBe(true); // prefix with dash
53
+
54
+ // Invalid edge cases (should be false)
55
+ expect(isRecipientValid("a::1")).toBe(false); // too short hex
56
+ expect(isRecipientValid("a::a")).toBe(false); // too short hex
57
+ expect(isRecipientValid("_::1")).toBe(false); // invalid prefix character
58
+ expect(isRecipientValid(".::1")).toBe(false); // invalid prefix character
66
59
  });
67
60
 
68
- it("should handle addresses with spaces and multiple colons", () => {
69
- // These are valid according to our regex but might not be ideal Canton addresses
70
- expect(isRecipientValid(" abc::123")).toBe(true); // space before address
71
- expect(isRecipientValid(" abc::abc")).toBe(true); // space before address with letters
72
- expect(isRecipientValid("abc ::123")).toBe(true); // space before ::
73
- expect(isRecipientValid("abc ::abc")).toBe(true); // space before :: with letters
74
- expect(isRecipientValid("abc::123::456")).toBe(true); // multiple ::
75
- expect(isRecipientValid("abc::abc::def")).toBe(true); // multiple :: with letters
61
+ it("should reject addresses with spaces and multiple colons", () => {
62
+ expect(isRecipientValid(" abc::123")).toBe(false); // space before address
63
+ expect(isRecipientValid(" abc::abc")).toBe(false); // space before address with letters
64
+ expect(isRecipientValid("abc ::123")).toBe(false); // space before ::
65
+ expect(isRecipientValid("abc ::abc")).toBe(false); // space before :: with letters
66
+ expect(isRecipientValid("abc::123::456")).toBe(false); // multiple ::
67
+ expect(isRecipientValid("abc::abc::def")).toBe(false); // multiple :: with letters
76
68
  });
77
69
  });
78
70
 
@@ -8,9 +8,9 @@ export const validateTag = (tag: BigNumber) => {
8
8
  );
9
9
  };
10
10
 
11
- const CANTON_ADDRESS_REGEX = /^.+::[a-zA-Z0-9]+$/;
11
+ const CANTON_ADDRESS_REGEX = /^[a-zA-Z0-9-]+::[a-fA-F0-9]{68}$/;
12
12
 
13
13
  export function isRecipientValid(recipient: string): boolean {
14
- // Canton address format: at least 1 character :: at least 1 alphanumeric character
14
+ // Canton address format: alphanumeric with dashes :: 68 hexadecimal characters
15
15
  return CANTON_ADDRESS_REGEX.test(recipient);
16
16
  }
@@ -83,12 +83,9 @@ describe("gateway (devnet)", () => {
83
83
  const signature = keyPair.sign(prepareResponse.transactions.combined_hash);
84
84
 
85
85
  // WHEN
86
- const response = await submitOnboarding(
87
- mockCurrency,
88
- keyPair.publicKeyHex,
89
- prepareResponse,
86
+ const response = await submitOnboarding(mockCurrency, keyPair.publicKeyHex, prepareResponse, {
90
87
  signature,
91
- );
88
+ });
92
89
 
93
90
  // Save onboarded account for next tests that need a valid party ID
94
91
  onboardedAccount = {
@@ -107,6 +104,8 @@ describe("gateway (devnet)", () => {
107
104
  testIfPrepared(
108
105
  "should not throw when already onboarded",
109
106
  async () => {
107
+ // Add delay to ensure previous operations are complete
108
+ await new Promise(resolve => setTimeout(resolve, 10000));
110
109
  // GIVEN
111
110
  const { keyPair } = getOnboardedAccount();
112
111
  const signature = keyPair.sign(prepareResponse!.transactions.combined_hash);
@@ -116,7 +115,7 @@ describe("gateway (devnet)", () => {
116
115
  mockCurrency,
117
116
  keyPair.publicKeyHex,
118
117
  prepareResponse!,
119
- signature,
118
+ { signature },
120
119
  );
121
120
 
122
121
  // THEN
@@ -10,6 +10,7 @@ import {
10
10
  PreApprovalResult,
11
11
  } from "../types/onboard";
12
12
  import type { CryptoCurrency } from "@ledgerhq/types-cryptoassets";
13
+ import type { CantonSignature } from "../types/signer";
13
14
 
14
15
  export type OnboardingPrepareResponse = {
15
16
  party_id: string;
@@ -33,6 +34,8 @@ export type OnboardingPrepareResponse = {
33
34
  };
34
35
  combined_hash: string;
35
36
  };
37
+ challenge_nonce?: string;
38
+ challenge_deadline?: number;
36
39
  };
37
40
 
38
41
  type OnboardingPrepareRequest = {
@@ -59,6 +62,7 @@ type OnboardingSubmitRequest = {
59
62
  prepare_request: OnboardingPrepareRequest;
60
63
  prepare_response: OnboardingPrepareResponse;
61
64
  signature: string;
65
+ application_signature?: string;
62
66
  };
63
67
 
64
68
  type OnboardingSubmitResponse = {
@@ -87,6 +91,7 @@ export type InstrumentBalance = {
87
91
  instrument_id: string;
88
92
  amount: string;
89
93
  locked: boolean;
94
+ utxo_count: number;
90
95
  };
91
96
 
92
97
  type PartyInfo = {
@@ -283,7 +288,8 @@ export type OperationInfo =
283
288
  const getGatewayUrl = (currency: CryptoCurrency) => coinConfig.getCoinConfig(currency).gatewayUrl;
284
289
  const getNodeId = (currency: CryptoCurrency) =>
285
290
  coinConfig.getCoinConfig(currency).nodeId || "ledger-live-devnet";
286
- const getNetworkType = (currency: CryptoCurrency) => coinConfig.getCoinConfig(currency).networkType;
291
+ export const getNetworkType = (currency: CryptoCurrency) =>
292
+ coinConfig.getCoinConfig(currency).networkType;
287
293
 
288
294
  const gatewayNetwork = <T, U = unknown>(req: LiveNetworkRequest<U>) => {
289
295
  const API_KEY = getEnv("CANTON_API_KEY");
@@ -324,7 +330,7 @@ export async function submitOnboarding(
324
330
  currency: CryptoCurrency,
325
331
  publicKey: string,
326
332
  prepareResponse: OnboardingPrepareResponse,
327
- signature: string,
333
+ { signature, applicationSignature }: CantonSignature,
328
334
  ) {
329
335
  try {
330
336
  const { data } = await gatewayNetwork<OnboardingSubmitResponse, OnboardingSubmitRequest>({
@@ -337,6 +343,7 @@ export async function submitOnboarding(
337
343
  },
338
344
  prepare_response: prepareResponse,
339
345
  signature,
346
+ ...(applicationSignature ? { application_signature: applicationSignature } : {}),
340
347
  },
341
348
  });
342
349
  return data;
@@ -448,18 +455,13 @@ export async function prepareTapRequest(
448
455
  currency: CryptoCurrency,
449
456
  { partyId, amount = 1000000 }: PrepareTapRequest,
450
457
  ) {
451
- if (getNetworkType(currency) === "mainnet") {
452
- return {
453
- serialized: "",
454
- json: null,
455
- hash: "",
456
- };
457
- }
458
+ const fixedPointAmount = BigInt(amount) * BigInt(10) ** BigInt(38);
459
+
458
460
  const { data } = await gatewayNetwork<PrepareTapResponse, { amount: string; type: string }>({
459
461
  method: "POST",
460
462
  url: `${getGatewayUrl(currency)}/v1/node/${getNodeId(currency)}/party/${partyId}/transaction/prepare`,
461
463
  data: {
462
- amount: amount.toString(),
464
+ amount: fixedPointAmount.toString(),
463
465
  type: TransactionType.TAP_REQUEST,
464
466
  },
465
467
  });
@@ -505,6 +507,7 @@ export async function prepareTransferRequest(
505
507
  url: `${getGatewayUrl(currency)}/v1/node/${getNodeId(currency)}/party/${partyId}/transaction/prepare`,
506
508
  data: params,
507
509
  });
510
+
508
511
  return data;
509
512
  }
510
513