@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.
- package/.turbo/turbo-build.log +1 -1
- package/.unimportedrc.json +2 -1
- package/CHANGELOG.md +26 -9
- package/README.md +75 -0
- package/lib/bridge/deviceTransactionConfig.d.ts +1 -1
- package/lib/bridge/deviceTransactionConfig.d.ts.map +1 -1
- package/lib/bridge/deviceTransactionConfig.js +1 -1
- package/lib/bridge/deviceTransactionConfig.js.map +1 -1
- package/lib/bridge/estimateMaxSpendable.d.ts +2 -2
- package/lib/bridge/estimateMaxSpendable.d.ts.map +1 -1
- package/lib/bridge/estimateMaxSpendable.js +2 -3
- package/lib/bridge/estimateMaxSpendable.js.map +1 -1
- package/lib/bridge/getTransactionStatus.d.ts +5 -3
- package/lib/bridge/getTransactionStatus.d.ts.map +1 -1
- package/lib/bridge/getTransactionStatus.js +27 -10
- package/lib/bridge/getTransactionStatus.js.map +1 -1
- package/lib/bridge/index.d.ts +2 -2
- package/lib/bridge/index.d.ts.map +1 -1
- package/lib/bridge/index.js +3 -3
- package/lib/bridge/index.js.map +1 -1
- package/lib/bridge/onboard.d.ts.map +1 -1
- package/lib/bridge/onboard.js +48 -22
- package/lib/bridge/onboard.js.map +1 -1
- package/lib/bridge/prepareTransaction.js +1 -1
- package/lib/bridge/prepareTransaction.js.map +1 -1
- package/lib/bridge/serialization.d.ts +4 -0
- package/lib/bridge/serialization.d.ts.map +1 -0
- package/lib/bridge/serialization.js +36 -0
- package/lib/bridge/serialization.js.map +1 -0
- package/lib/bridge/signOperation.d.ts.map +1 -1
- package/lib/bridge/signOperation.js +11 -4
- package/lib/bridge/signOperation.js.map +1 -1
- package/lib/bridge/sync.d.ts.map +1 -1
- package/lib/bridge/sync.js +14 -6
- package/lib/bridge/sync.js.map +1 -1
- package/lib/bridge/transaction.js +1 -1
- package/lib/bridge/transaction.js.map +1 -1
- package/lib/common-logic/account/getBalance.d.ts +5 -1
- package/lib/common-logic/account/getBalance.d.ts.map +1 -1
- package/lib/common-logic/account/getBalance.js +2 -0
- package/lib/common-logic/account/getBalance.js.map +1 -1
- package/lib/common-logic/index.d.ts +1 -0
- package/lib/common-logic/index.d.ts.map +1 -1
- package/lib/common-logic/index.js +3 -1
- package/lib/common-logic/index.js.map +1 -1
- package/lib/common-logic/transaction/craftTransaction.js +1 -1
- package/lib/common-logic/transaction/craftTransaction.js.map +1 -1
- package/lib/common-logic/transaction/estimateFees.js +1 -1
- package/lib/common-logic/transaction/estimateFees.js.map +1 -1
- package/lib/common-logic/transaction/sign.d.ts +8 -0
- package/lib/common-logic/transaction/sign.d.ts.map +1 -0
- package/lib/common-logic/transaction/sign.js +45 -0
- package/lib/common-logic/transaction/sign.js.map +1 -0
- package/lib/common-logic/transaction/split.d.ts +9 -0
- package/lib/common-logic/transaction/split.d.ts.map +1 -0
- package/lib/common-logic/transaction/split.js +119 -0
- package/lib/common-logic/transaction/split.js.map +1 -0
- package/lib/common-logic/utils.js +2 -2
- package/lib/common-logic/utils.js.map +1 -1
- package/lib/network/gateway.d.ts +6 -1
- package/lib/network/gateway.d.ts.map +1 -1
- package/lib/network/gateway.js +6 -9
- package/lib/network/gateway.js.map +1 -1
- package/lib/test/cantonTestUtils.d.ts +4 -9
- package/lib/test/cantonTestUtils.d.ts.map +1 -1
- package/lib/test/cantonTestUtils.js +736 -27
- package/lib/test/cantonTestUtils.js.map +1 -1
- package/lib/test/fixtures.d.ts +5 -0
- package/lib/test/fixtures.d.ts.map +1 -0
- package/lib/test/fixtures.js +57 -0
- package/lib/test/fixtures.js.map +1 -0
- package/lib/types/bridge.d.ts +14 -2
- package/lib/types/bridge.d.ts.map +1 -1
- package/lib/types/errors.d.ts +6 -0
- package/lib/types/errors.d.ts.map +1 -1
- package/lib/types/errors.js +3 -1
- package/lib/types/errors.js.map +1 -1
- package/lib/types/index.d.ts +1 -0
- package/lib/types/index.d.ts.map +1 -1
- package/lib/types/index.js +1 -0
- package/lib/types/index.js.map +1 -1
- package/lib/types/signer.d.ts +15 -2
- package/lib/types/signer.d.ts.map +1 -1
- package/lib/types/transaction-proto.json +1238 -0
- package/lib-es/bridge/deviceTransactionConfig.d.ts +1 -1
- package/lib-es/bridge/deviceTransactionConfig.d.ts.map +1 -1
- package/lib-es/bridge/deviceTransactionConfig.js +1 -1
- package/lib-es/bridge/deviceTransactionConfig.js.map +1 -1
- package/lib-es/bridge/estimateMaxSpendable.d.ts +2 -2
- package/lib-es/bridge/estimateMaxSpendable.d.ts.map +1 -1
- package/lib-es/bridge/estimateMaxSpendable.js +2 -3
- package/lib-es/bridge/estimateMaxSpendable.js.map +1 -1
- package/lib-es/bridge/getTransactionStatus.d.ts +5 -3
- package/lib-es/bridge/getTransactionStatus.d.ts.map +1 -1
- package/lib-es/bridge/getTransactionStatus.js +27 -10
- package/lib-es/bridge/getTransactionStatus.js.map +1 -1
- package/lib-es/bridge/index.d.ts +2 -2
- package/lib-es/bridge/index.d.ts.map +1 -1
- package/lib-es/bridge/index.js +3 -3
- package/lib-es/bridge/index.js.map +1 -1
- package/lib-es/bridge/onboard.d.ts.map +1 -1
- package/lib-es/bridge/onboard.js +49 -23
- package/lib-es/bridge/onboard.js.map +1 -1
- package/lib-es/bridge/prepareTransaction.js +1 -1
- package/lib-es/bridge/prepareTransaction.js.map +1 -1
- package/lib-es/bridge/serialization.d.ts +4 -0
- package/lib-es/bridge/serialization.d.ts.map +1 -0
- package/lib-es/bridge/serialization.js +32 -0
- package/lib-es/bridge/serialization.js.map +1 -0
- package/lib-es/bridge/signOperation.d.ts.map +1 -1
- package/lib-es/bridge/signOperation.js +11 -4
- package/lib-es/bridge/signOperation.js.map +1 -1
- package/lib-es/bridge/sync.d.ts.map +1 -1
- package/lib-es/bridge/sync.js +14 -6
- package/lib-es/bridge/sync.js.map +1 -1
- package/lib-es/bridge/transaction.js +1 -1
- package/lib-es/bridge/transaction.js.map +1 -1
- package/lib-es/common-logic/account/getBalance.d.ts +5 -1
- package/lib-es/common-logic/account/getBalance.d.ts.map +1 -1
- package/lib-es/common-logic/account/getBalance.js +2 -0
- package/lib-es/common-logic/account/getBalance.js.map +1 -1
- package/lib-es/common-logic/index.d.ts +1 -0
- package/lib-es/common-logic/index.d.ts.map +1 -1
- package/lib-es/common-logic/index.js +1 -0
- package/lib-es/common-logic/index.js.map +1 -1
- package/lib-es/common-logic/transaction/craftTransaction.js +1 -1
- package/lib-es/common-logic/transaction/craftTransaction.js.map +1 -1
- package/lib-es/common-logic/transaction/estimateFees.js +1 -1
- package/lib-es/common-logic/transaction/estimateFees.js.map +1 -1
- package/lib-es/common-logic/transaction/sign.d.ts +8 -0
- package/lib-es/common-logic/transaction/sign.d.ts.map +1 -0
- package/lib-es/common-logic/transaction/sign.js +42 -0
- package/lib-es/common-logic/transaction/sign.js.map +1 -0
- package/lib-es/common-logic/transaction/split.d.ts +9 -0
- package/lib-es/common-logic/transaction/split.d.ts.map +1 -0
- package/lib-es/common-logic/transaction/split.js +83 -0
- package/lib-es/common-logic/transaction/split.js.map +1 -0
- package/lib-es/common-logic/utils.js +2 -2
- package/lib-es/common-logic/utils.js.map +1 -1
- package/lib-es/network/gateway.d.ts +6 -1
- package/lib-es/network/gateway.d.ts.map +1 -1
- package/lib-es/network/gateway.js +5 -10
- package/lib-es/network/gateway.js.map +1 -1
- package/lib-es/test/cantonTestUtils.d.ts +4 -9
- package/lib-es/test/cantonTestUtils.d.ts.map +1 -1
- package/lib-es/test/cantonTestUtils.js +697 -21
- package/lib-es/test/cantonTestUtils.js.map +1 -1
- package/lib-es/test/fixtures.d.ts +5 -0
- package/lib-es/test/fixtures.d.ts.map +1 -0
- package/lib-es/test/fixtures.js +49 -0
- package/lib-es/test/fixtures.js.map +1 -0
- package/lib-es/types/bridge.d.ts +14 -2
- package/lib-es/types/bridge.d.ts.map +1 -1
- package/lib-es/types/errors.d.ts +6 -0
- package/lib-es/types/errors.d.ts.map +1 -1
- package/lib-es/types/errors.js +2 -0
- package/lib-es/types/errors.js.map +1 -1
- package/lib-es/types/index.d.ts +1 -0
- package/lib-es/types/index.d.ts.map +1 -1
- package/lib-es/types/index.js +1 -0
- package/lib-es/types/index.js.map +1 -1
- package/lib-es/types/signer.d.ts +15 -2
- package/lib-es/types/signer.d.ts.map +1 -1
- package/lib-es/types/transaction-proto.json +1238 -0
- package/package.json +13 -10
- package/scripts/generate.js +261 -0
- package/src/bridge/deviceTransactionConfig.test.ts +14 -10
- package/src/bridge/deviceTransactionConfig.ts +2 -2
- package/src/bridge/estimateMaxSpendable.ts +6 -8
- package/src/bridge/getTransactionStatus.test.ts +103 -165
- package/src/bridge/getTransactionStatus.ts +43 -11
- package/src/bridge/index.ts +6 -5
- package/src/bridge/onboard.integ.test.ts +8 -51
- package/src/bridge/onboard.ts +58 -33
- package/src/bridge/prepareTransaction.ts +1 -1
- package/src/bridge/serialization.ts +44 -0
- package/src/bridge/signOperation.test.ts +123 -0
- package/src/bridge/signOperation.ts +13 -6
- package/src/bridge/sync.integ.test.ts +157 -132
- package/src/bridge/sync.test.ts +5 -1
- package/src/bridge/sync.ts +18 -7
- package/src/bridge/transaction.ts +1 -1
- package/src/common-logic/account/getBalance.ts +12 -2
- package/src/common-logic/account/getBalance.unit.test.ts +7 -1
- package/src/common-logic/index.ts +1 -0
- package/src/common-logic/transaction/craftTransaction.ts +1 -1
- package/src/common-logic/transaction/estimateFees.test.ts +10 -0
- package/src/common-logic/transaction/estimateFees.ts +1 -1
- package/src/common-logic/transaction/sign.test.ts +389 -0
- package/src/common-logic/transaction/sign.ts +59 -0
- package/src/common-logic/transaction/split.test.ts +50 -0
- package/src/common-logic/transaction/split.ts +101 -0
- package/src/common-logic/utils.test.ts +22 -30
- package/src/common-logic/utils.ts +2 -2
- package/src/network/gateway.integ.test.ts +5 -6
- package/src/network/gateway.ts +13 -10
- package/src/test/cantonTestUtils.ts +789 -24
- package/src/test/fixtures.ts +53 -0
- package/src/test/prepare-transfer-serialized.json +26 -0
- package/src/test/prepare-transfer.json +3298 -0
- package/src/types/bridge.ts +15 -2
- package/src/types/errors.ts +3 -0
- package/src/types/index.ts +1 -0
- package/src/types/signer.ts +21 -3
- 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
|
-
"
|
|
9
|
-
"
|
|
10
|
-
"
|
|
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
|
-
|
|
57
|
-
expect(isRecipientValid(
|
|
58
|
-
expect(isRecipientValid(
|
|
59
|
-
expect(isRecipientValid(
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
expect(isRecipientValid("
|
|
63
|
-
expect(isRecipientValid("
|
|
64
|
-
expect(isRecipientValid("
|
|
65
|
-
expect(isRecipientValid(".::
|
|
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
|
|
69
|
-
|
|
70
|
-
expect(isRecipientValid(" abc::
|
|
71
|
-
expect(isRecipientValid("
|
|
72
|
-
expect(isRecipientValid("abc ::
|
|
73
|
-
expect(isRecipientValid("abc
|
|
74
|
-
expect(isRecipientValid("abc::
|
|
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 =
|
|
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:
|
|
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
|
package/src/network/gateway.ts
CHANGED
|
@@ -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) =>
|
|
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:
|
|
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
|
-
|
|
452
|
-
|
|
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:
|
|
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
|
|