@ledgerhq/coin-internet_computer 1.21.2 → 1.22.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/.unimportedrc.json +19 -7
- package/CHANGELOG.md +38 -0
- package/jest.config.js +2 -1
- package/jest.integ.config.js +18 -0
- package/lib/api/api.d.ts +2 -1
- package/lib/api/api.d.ts.map +1 -1
- package/lib/api/api.js +51 -3
- package/lib/api/api.js.map +1 -1
- package/lib/bridge/broadcast.d.ts.map +1 -1
- package/lib/bridge/broadcast.js +9 -6
- package/lib/bridge/broadcast.js.map +1 -1
- package/lib/bridge/signOperation.d.ts.map +1 -1
- package/lib/bridge/signOperation.js +2 -0
- package/lib/bridge/signOperation.js.map +1 -1
- package/lib-es/api/api.d.ts +2 -1
- package/lib-es/api/api.d.ts.map +1 -1
- package/lib-es/api/api.js +50 -3
- package/lib-es/api/api.js.map +1 -1
- package/lib-es/bridge/broadcast.d.ts.map +1 -1
- package/lib-es/bridge/broadcast.js +10 -7
- package/lib-es/bridge/broadcast.js.map +1 -1
- package/lib-es/bridge/signOperation.d.ts.map +1 -1
- package/lib-es/bridge/signOperation.js +3 -1
- package/lib-es/bridge/signOperation.js.map +1 -1
- package/package.json +10 -5
- package/src/api/api.ts +75 -4
- package/src/bridge/broadcast.integ.test.ts +51 -0
- package/src/bridge/broadcast.ts +11 -7
- package/src/bridge/broadcast.unit.test.ts +67 -0
- package/src/bridge/signOperation.ts +3 -1
package/.unimportedrc.json
CHANGED
|
@@ -5,9 +5,6 @@
|
|
|
5
5
|
"src/bridge/bridgeHelpers/account.ts",
|
|
6
6
|
"src/bridge/bridgeHelpers/addresses.ts",
|
|
7
7
|
"src/bridge/bridgeHelpers/fee.ts",
|
|
8
|
-
"src/bridge/bridgeHelpers/icpRosetta/index.ts",
|
|
9
|
-
"src/bridge/bridgeHelpers/icpRosetta/types.ts",
|
|
10
|
-
"src/bridge/bridgeHelpers/icpRosetta/utils.ts",
|
|
11
8
|
"src/bridge/broadcast.ts",
|
|
12
9
|
"src/bridge/buildOptimisticOperation.ts",
|
|
13
10
|
"src/bridge/createTransaction.ts",
|
|
@@ -34,11 +31,26 @@
|
|
|
34
31
|
"src/types/index.ts",
|
|
35
32
|
"src/types/signer.ts"
|
|
36
33
|
],
|
|
34
|
+
"ignorePatterns": [
|
|
35
|
+
"**/node_modules/**",
|
|
36
|
+
"**/*.fixture.ts",
|
|
37
|
+
"**/*.mock.ts",
|
|
38
|
+
"**/*.test.{js,jsx,ts,tsx}",
|
|
39
|
+
"**/*.integ.test.ts"
|
|
40
|
+
],
|
|
37
41
|
"ignoreUnresolved": [
|
|
38
42
|
"@jest/expect-utils",
|
|
39
43
|
"@jest/get-type",
|
|
40
|
-
"jest-util",
|
|
41
|
-
|
|
42
|
-
"
|
|
43
|
-
|
|
44
|
+
"jest-util",
|
|
45
|
+
"form-data",
|
|
46
|
+
"proxy-from-env",
|
|
47
|
+
"follow-redirects",
|
|
48
|
+
"buffer/",
|
|
49
|
+
"@noble/hashes/sha256",
|
|
50
|
+
"borc",
|
|
51
|
+
"simple-cbor",
|
|
52
|
+
"@noble/curves/bls12-381",
|
|
53
|
+
"@noble/curves/ed25519"
|
|
54
|
+
],
|
|
55
|
+
"ignoreUnimported": ["src/supportedFeatures.ts"]
|
|
44
56
|
}
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,43 @@
|
|
|
1
1
|
# @ledgerhq/coin-internet_computer
|
|
2
2
|
|
|
3
|
+
## 1.22.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#16710](https://github.com/LedgerHQ/ledger-live/pull/16710) [`0ef1cbe`](https://github.com/LedgerHQ/ledger-live/commit/0ef1cbea42e651de9589022d9f448e6450d2ff00) Thanks [@francois-guerin-ledger](https://github.com/francois-guerin-ledger)! - test(coin-modules): ensure we throw when broadcast fails
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- Updated dependencies [[`ed0dc8a`](https://github.com/LedgerHQ/ledger-live/commit/ed0dc8abc2c8f5054e655c4e12efe6fb433fbaca), [`4ddd97a`](https://github.com/LedgerHQ/ledger-live/commit/4ddd97a99bab5b581ad5ccfd36eb420ec4ee6352), [`7fafa10`](https://github.com/LedgerHQ/ledger-live/commit/7fafa10d8af581f4433a60ea908980a726d3a777), [`ac26c8b`](https://github.com/LedgerHQ/ledger-live/commit/ac26c8bffa9b5cc9f28bed5ce3d44e32982d655c), [`fb79639`](https://github.com/LedgerHQ/ledger-live/commit/fb79639eb81258bae4830ed6ffe375ae625054ad), [`0d11df6`](https://github.com/LedgerHQ/ledger-live/commit/0d11df6ef8dc781171071824ad1c39e3beed7730), [`321a0e2`](https://github.com/LedgerHQ/ledger-live/commit/321a0e2ce948fac11f7bdf0e106eb0af57168caa), [`d308b1a`](https://github.com/LedgerHQ/ledger-live/commit/d308b1a6b9c629839f051cf367a527f4232120c7), [`21e69fe`](https://github.com/LedgerHQ/ledger-live/commit/21e69fea49cffc0b1204903e539a64b83e4b28f0), [`e6dc658`](https://github.com/LedgerHQ/ledger-live/commit/e6dc658b83ebd2102e19a1fead021443457c05d9), [`fb4d165`](https://github.com/LedgerHQ/ledger-live/commit/fb4d1656be8dc8e933e55600970a2e991fbaeebb), [`73bfe05`](https://github.com/LedgerHQ/ledger-live/commit/73bfe055ec23e0d630f2da9f4dbc9731b6fe5190)]:
|
|
12
|
+
- @ledgerhq/types-live@6.107.0
|
|
13
|
+
- @ledgerhq/ledger-wallet-framework@1.4.0
|
|
14
|
+
- @ledgerhq/errors@6.35.0
|
|
15
|
+
- @ledgerhq/cryptoassets@13.47.0
|
|
16
|
+
- @ledgerhq/devices@8.14.2
|
|
17
|
+
|
|
18
|
+
## 1.22.0-next.1
|
|
19
|
+
|
|
20
|
+
### Patch Changes
|
|
21
|
+
|
|
22
|
+
- Updated dependencies [[`e6dc658`](https://github.com/LedgerHQ/ledger-live/commit/e6dc658b83ebd2102e19a1fead021443457c05d9)]:
|
|
23
|
+
- @ledgerhq/cryptoassets@13.47.0-next.1
|
|
24
|
+
- @ledgerhq/ledger-wallet-framework@1.4.0-next.1
|
|
25
|
+
|
|
26
|
+
## 1.22.0-next.0
|
|
27
|
+
|
|
28
|
+
### Minor Changes
|
|
29
|
+
|
|
30
|
+
- [#16710](https://github.com/LedgerHQ/ledger-live/pull/16710) [`0ef1cbe`](https://github.com/LedgerHQ/ledger-live/commit/0ef1cbea42e651de9589022d9f448e6450d2ff00) Thanks [@francois-guerin-ledger](https://github.com/francois-guerin-ledger)! - test(coin-modules): ensure we throw when broadcast fails
|
|
31
|
+
|
|
32
|
+
### Patch Changes
|
|
33
|
+
|
|
34
|
+
- Updated dependencies [[`ed0dc8a`](https://github.com/LedgerHQ/ledger-live/commit/ed0dc8abc2c8f5054e655c4e12efe6fb433fbaca), [`4ddd97a`](https://github.com/LedgerHQ/ledger-live/commit/4ddd97a99bab5b581ad5ccfd36eb420ec4ee6352), [`7fafa10`](https://github.com/LedgerHQ/ledger-live/commit/7fafa10d8af581f4433a60ea908980a726d3a777), [`ac26c8b`](https://github.com/LedgerHQ/ledger-live/commit/ac26c8bffa9b5cc9f28bed5ce3d44e32982d655c), [`fb79639`](https://github.com/LedgerHQ/ledger-live/commit/fb79639eb81258bae4830ed6ffe375ae625054ad), [`0d11df6`](https://github.com/LedgerHQ/ledger-live/commit/0d11df6ef8dc781171071824ad1c39e3beed7730), [`321a0e2`](https://github.com/LedgerHQ/ledger-live/commit/321a0e2ce948fac11f7bdf0e106eb0af57168caa), [`d308b1a`](https://github.com/LedgerHQ/ledger-live/commit/d308b1a6b9c629839f051cf367a527f4232120c7), [`21e69fe`](https://github.com/LedgerHQ/ledger-live/commit/21e69fea49cffc0b1204903e539a64b83e4b28f0), [`fb4d165`](https://github.com/LedgerHQ/ledger-live/commit/fb4d1656be8dc8e933e55600970a2e991fbaeebb), [`73bfe05`](https://github.com/LedgerHQ/ledger-live/commit/73bfe055ec23e0d630f2da9f4dbc9731b6fe5190)]:
|
|
35
|
+
- @ledgerhq/types-live@6.107.0-next.0
|
|
36
|
+
- @ledgerhq/ledger-wallet-framework@1.4.0-next.0
|
|
37
|
+
- @ledgerhq/errors@6.35.0-next.0
|
|
38
|
+
- @ledgerhq/cryptoassets@13.47.0-next.0
|
|
39
|
+
- @ledgerhq/devices@8.14.2-next.0
|
|
40
|
+
|
|
3
41
|
## 1.21.2
|
|
4
42
|
|
|
5
43
|
### Patch Changes
|
package/jest.config.js
CHANGED
|
@@ -18,9 +18,10 @@ module.exports = {
|
|
|
18
18
|
},
|
|
19
19
|
coverageReporters: ["json", ["lcov", { file: "lcov.info", projectRoot: "../../../" }], "text"],
|
|
20
20
|
testEnvironment: "node",
|
|
21
|
-
testPathIgnorePatterns: ["lib/", "lib-es/", ".integration.test.ts"],
|
|
21
|
+
testPathIgnorePatterns: ["lib/", "lib-es/", ".integration.test.ts", "\\.integ\\.test\\.ts$"],
|
|
22
22
|
reporters: [
|
|
23
23
|
"default",
|
|
24
|
+
...(process.env.CI ? ["github-actions"] : []),
|
|
24
25
|
["jest-sonar", { outputName: "sonar-executionTests-report.xml", reportedFilePath: "absolute" }],
|
|
25
26
|
],
|
|
26
27
|
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/** @type {import('jest').Config} */
|
|
2
|
+
module.exports = {
|
|
3
|
+
testEnvironment: "node",
|
|
4
|
+
testRegex: ".integ.test.ts$",
|
|
5
|
+
testPathIgnorePatterns: ["lib/", "lib-es/"],
|
|
6
|
+
testTimeout: 60_000,
|
|
7
|
+
forceExit: true,
|
|
8
|
+
transform: {
|
|
9
|
+
"^.+\\.(t|j)sx?$": [
|
|
10
|
+
"@swc/jest",
|
|
11
|
+
{
|
|
12
|
+
jsc: {
|
|
13
|
+
target: "esnext",
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
],
|
|
17
|
+
},
|
|
18
|
+
};
|
package/lib/api/api.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { TransactionWithId } from "@zondax/ledger-live-icp";
|
|
2
2
|
import BigNumber from "bignumber.js";
|
|
3
3
|
export declare const fetchBlockHeight: () => Promise<BigNumber>;
|
|
4
|
-
export declare const broadcastTxn: (payload: Buffer, canisterId: string, type: "call" | "read_state") => Promise<ArrayBuffer
|
|
4
|
+
export declare const broadcastTxn: (payload: Buffer, canisterId: string, type: "call" | "read_state") => Promise<Uint8Array<ArrayBuffer>>;
|
|
5
|
+
export declare const ensureTransferCallAccepted: (syncCallResponse: Uint8Array, transferRequestIdHex: string) => Promise<void>;
|
|
5
6
|
export declare const fetchBalance: (address: string) => Promise<BigNumber>;
|
|
6
7
|
export declare const fetchTxns: (address: string, startBlockHeight: bigint, stopBlockHeight?: bigint) => Promise<TransactionWithId[]>;
|
|
7
8
|
//# sourceMappingURL=api.d.ts.map
|
package/lib/api/api.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../src/api/api.ts"],"names":[],"mappings":"AAEA,OAAO,EAQL,iBAAiB,EAClB,MAAM,yBAAyB,CAAC;AAGjC,OAAO,SAAS,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../src/api/api.ts"],"names":[],"mappings":"AAEA,OAAO,EAQL,iBAAiB,EAClB,MAAM,yBAAyB,CAAC;AAGjC,OAAO,SAAS,MAAM,cAAc,CAAC;AAkDrC,eAAO,MAAM,gBAAgB,QAAa,OAAO,CAAC,SAAS,CA0B1D,CAAC;AAEF,eAAO,MAAM,YAAY,GACvB,SAAS,MAAM,EACf,YAAY,MAAM,EAClB,MAAM,MAAM,GAAG,YAAY,qCAgB5B,CAAC;AAEF,eAAO,MAAM,0BAA0B,GACrC,kBAAkB,UAAU,EAC5B,sBAAsB,MAAM,kBA0B7B,CAAC;AAEF,eAAO,MAAM,YAAY,GAAU,SAAS,MAAM,KAAG,OAAO,CAAC,SAAS,CAuBrE,CAAC;AAEF,eAAO,MAAM,SAAS,GACpB,SAAS,MAAM,EACf,kBAAkB,MAAM,EACxB,wBAA2B,KAC1B,OAAO,CAAC,iBAAiB,EAAE,CA6C7B,CAAC"}
|
package/lib/api/api.js
CHANGED
|
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.fetchTxns = exports.fetchBalance = exports.broadcastTxn = exports.fetchBlockHeight = void 0;
|
|
6
|
+
exports.fetchTxns = exports.fetchBalance = exports.ensureTransferCallAccepted = exports.broadcastTxn = exports.fetchBlockHeight = void 0;
|
|
7
7
|
const logs_1 = require("@ledgerhq/logs");
|
|
8
8
|
const ledger_live_icp_1 = require("@zondax/ledger-live-icp");
|
|
9
9
|
const agent_1 = require("@zondax/ledger-live-icp/agent");
|
|
@@ -11,6 +11,37 @@ const utils_1 = require("@zondax/ledger-live-icp/utils");
|
|
|
11
11
|
const bignumber_js_1 = __importDefault(require("bignumber.js"));
|
|
12
12
|
const invariant_1 = __importDefault(require("invariant"));
|
|
13
13
|
const consts_1 = require("../consts");
|
|
14
|
+
function toArrayBuffer(view) {
|
|
15
|
+
if (view instanceof ArrayBuffer) {
|
|
16
|
+
return view;
|
|
17
|
+
}
|
|
18
|
+
const copy = new Uint8Array(view.byteLength);
|
|
19
|
+
copy.set(view);
|
|
20
|
+
return copy.buffer;
|
|
21
|
+
}
|
|
22
|
+
function requestIdFromHex(hex) {
|
|
23
|
+
const bytes = Buffer.from(hex, "hex");
|
|
24
|
+
const copy = new Uint8Array(bytes);
|
|
25
|
+
return copy.buffer;
|
|
26
|
+
}
|
|
27
|
+
function throwIfLedgerTransferReplyIsErr(replyBuf) {
|
|
28
|
+
const transferIdlFunc = (0, ledger_live_icp_1.getCanisterIdlFunc)(ledger_live_icp_1.ledgerIdlFactory, "transfer");
|
|
29
|
+
const decoded = (0, ledger_live_icp_1.decodeCanisterIdlFunc)(transferIdlFunc, replyBuf);
|
|
30
|
+
const out = decoded[0];
|
|
31
|
+
if (out.Err) {
|
|
32
|
+
const message = JSON.stringify(out.Err, (_, v) => (typeof v === "bigint" ? v.toString() : v));
|
|
33
|
+
throw new Error(message);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
async function fetchRootKey() {
|
|
37
|
+
const res = await fetch(`${consts_1.ICP_NETWORK_URL}/api/v2/status`);
|
|
38
|
+
if (res.status !== 200) {
|
|
39
|
+
throw new Error(`Failed to fetch status: ${await res.text()}`);
|
|
40
|
+
}
|
|
41
|
+
const status = agent_1.Cbor.decode(await res.arrayBuffer());
|
|
42
|
+
(0, invariant_1.default)(status.root_key, "[ICP](fetchRootKey) Missing root_key in status response");
|
|
43
|
+
return toArrayBuffer(status.root_key);
|
|
44
|
+
}
|
|
14
45
|
const fetchBlockHeight = async () => {
|
|
15
46
|
const canisterId = ledger_live_icp_1.Principal.fromText(consts_1.MAINNET_LEDGER_CANISTER_ID);
|
|
16
47
|
const queryBlocksRawRequest = {
|
|
@@ -41,11 +72,28 @@ const broadcastTxn = async (payload, canisterId, type) => {
|
|
|
41
72
|
},
|
|
42
73
|
});
|
|
43
74
|
if (res.status === 200) {
|
|
44
|
-
return await res.arrayBuffer();
|
|
75
|
+
return new Uint8Array(await res.arrayBuffer());
|
|
45
76
|
}
|
|
46
|
-
throw new Error(`Failed to broadcast transaction: ${res.text()}`);
|
|
77
|
+
throw new Error(`Failed to broadcast transaction: ${await res.text()}`);
|
|
47
78
|
};
|
|
48
79
|
exports.broadcastTxn = broadcastTxn;
|
|
80
|
+
const ensureTransferCallAccepted = async (syncCallResponse, transferRequestIdHex) => {
|
|
81
|
+
const requestId = requestIdFromHex(transferRequestIdHex);
|
|
82
|
+
const canisterId = ledger_live_icp_1.Principal.fromText(consts_1.MAINNET_LEDGER_CANISTER_ID);
|
|
83
|
+
const top = agent_1.Cbor.decode(toArrayBuffer(syncCallResponse));
|
|
84
|
+
(0, invariant_1.default)(top.status === "replied" && top.certificate, "[ICP](ensureTransferCallAccepted) Decoding failed");
|
|
85
|
+
const rootKey = await fetchRootKey();
|
|
86
|
+
const cert = await agent_1.Certificate.create({
|
|
87
|
+
certificate: toArrayBuffer(top.certificate),
|
|
88
|
+
rootKey,
|
|
89
|
+
canisterId,
|
|
90
|
+
maxAgeInMinutes: 100,
|
|
91
|
+
});
|
|
92
|
+
const replyBuf = (0, agent_1.lookupResultToBuffer)(cert.lookup(["request_status", requestId, "reply"]));
|
|
93
|
+
(0, invariant_1.default)(replyBuf, "[ICP](ensureTransferCallAccepted) Reply status not found");
|
|
94
|
+
throwIfLedgerTransferReplyIsErr(replyBuf);
|
|
95
|
+
};
|
|
96
|
+
exports.ensureTransferCallAccepted = ensureTransferCallAccepted;
|
|
49
97
|
const fetchBalance = async (address) => {
|
|
50
98
|
const agent = await (0, agent_1.getAgent)(consts_1.ICP_NETWORK_URL);
|
|
51
99
|
const indexCanister = ledger_live_icp_1.Principal.fromText(consts_1.MAINNET_INDEX_CANISTER_ID);
|
package/lib/api/api.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api.js","sourceRoot":"","sources":["../../src/api/api.ts"],"names":[],"mappings":";;;;;;
|
|
1
|
+
{"version":3,"file":"api.js","sourceRoot":"","sources":["../../src/api/api.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"broadcast.d.ts","sourceRoot":"","sources":["../../src/bridge/broadcast.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAIrD,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"broadcast.d.ts","sourceRoot":"","sources":["../../src/bridge/broadcast.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAIrD,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAqBvC,eAAO,MAAM,SAAS,EAAE,aAAa,CAAC,WAAW,CAAC,CAAC,WAAW,CAiB7D,CAAC"}
|
package/lib/bridge/broadcast.js
CHANGED
|
@@ -8,12 +8,14 @@ const logs_1 = require("@ledgerhq/logs");
|
|
|
8
8
|
const invariant_1 = __importDefault(require("invariant"));
|
|
9
9
|
const api_1 = require("../api");
|
|
10
10
|
const consts_1 = require("../consts");
|
|
11
|
-
// Type guard to validate rawData shape
|
|
12
11
|
function isBroadcastRawData(data) {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
12
|
+
if (typeof data !== "object" || data === null) {
|
|
13
|
+
return false;
|
|
14
|
+
}
|
|
15
|
+
return ("encodedSignedCallBlob" in data &&
|
|
16
|
+
typeof data.encodedSignedCallBlob === "string" &&
|
|
17
|
+
"transferRequestIdHex" in data &&
|
|
18
|
+
typeof data.transferRequestIdHex === "string");
|
|
17
19
|
}
|
|
18
20
|
// Main broadcast function for handling Internet Computer transactions
|
|
19
21
|
const broadcast = async ({ signedOperation: { operation, rawData }, }) => {
|
|
@@ -21,7 +23,8 @@ const broadcast = async ({ signedOperation: { operation, rawData }, }) => {
|
|
|
21
23
|
// Validate rawData with type guard
|
|
22
24
|
(0, invariant_1.default)(isBroadcastRawData(rawData), "[ICP](broadcast) Invalid rawData format");
|
|
23
25
|
(0, invariant_1.default)(operation.extra, "[ICP](broadcast) Missing operation extra");
|
|
24
|
-
await (0, api_1.broadcastTxn)(Buffer.from(rawData.encodedSignedCallBlob, "hex"), consts_1.MAINNET_LEDGER_CANISTER_ID, "call");
|
|
26
|
+
const syncCallResponse = await (0, api_1.broadcastTxn)(Buffer.from(rawData.encodedSignedCallBlob, "hex"), consts_1.MAINNET_LEDGER_CANISTER_ID, "call");
|
|
27
|
+
await (0, api_1.ensureTransferCallAccepted)(syncCallResponse, rawData.transferRequestIdHex);
|
|
25
28
|
return operation;
|
|
26
29
|
};
|
|
27
30
|
exports.broadcast = broadcast;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"broadcast.js","sourceRoot":"","sources":["../../src/bridge/broadcast.ts"],"names":[],"mappings":";;;;;;AAAA,yCAAqC;AAErC,0DAAkC;AAClC,
|
|
1
|
+
{"version":3,"file":"broadcast.js","sourceRoot":"","sources":["../../src/bridge/broadcast.ts"],"names":[],"mappings":";;;;;;AAAA,yCAAqC;AAErC,0DAAkC;AAClC,gCAAkE;AAClE,sCAAuD;AAQvD,SAAS,kBAAkB,CAAC,IAAa;IACvC,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;QAC9C,OAAO,KAAK,CAAC;IACf,CAAC;IAED,OAAO,CACL,uBAAuB,IAAI,IAAI;QAC/B,OAAO,IAAI,CAAC,qBAAqB,KAAK,QAAQ;QAC9C,sBAAsB,IAAI,IAAI;QAC9B,OAAO,IAAI,CAAC,oBAAoB,KAAK,QAAQ,CAC9C,CAAC;AACJ,CAAC;AAED,sEAAsE;AAC/D,MAAM,SAAS,GAA4C,KAAK,EAAE,EACvE,eAAe,EAAE,EAAE,SAAS,EAAE,OAAO,EAAE,GACxC,EAAE,EAAE;IACH,IAAA,UAAG,EAAC,OAAO,EAAE,+DAA+D,CAAC,CAAC;IAE9E,mCAAmC;IACnC,IAAA,mBAAS,EAAC,kBAAkB,CAAC,OAAO,CAAC,EAAE,yCAAyC,CAAC,CAAC;IAClF,IAAA,mBAAS,EAAC,SAAS,CAAC,KAAK,EAAE,0CAA0C,CAAC,CAAC;IAEvE,MAAM,gBAAgB,GAAG,MAAM,IAAA,kBAAY,EACzC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,qBAAqB,EAAE,KAAK,CAAC,EACjD,mCAA0B,EAC1B,MAAM,CACP,CAAC;IACF,MAAM,IAAA,gCAA0B,EAAC,gBAAgB,EAAE,OAAO,CAAC,oBAAoB,CAAC,CAAC;IAEjF,OAAO,SAAS,CAAC;AACnB,CAAC,CAAC;AAjBW,QAAA,SAAS,aAiBpB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"signOperation.d.ts","sourceRoot":"","sources":["../../src/bridge/signOperation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,0CAA0C,CAAC;AAEzE,OAAO,EAAW,aAAa,EAAY,MAAM,sBAAsB,CAAC;AAWxE,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACvC,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AA6BrC,eAAO,MAAM,kBAAkB,GAC5B,eAAe,aAAa,CAAC,SAAS,CAAC,KAAG,aAAa,CAAC,WAAW,CAAC,CAAC,eAAe,
|
|
1
|
+
{"version":3,"file":"signOperation.d.ts","sourceRoot":"","sources":["../../src/bridge/signOperation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,0CAA0C,CAAC;AAEzE,OAAO,EAAW,aAAa,EAAY,MAAM,sBAAsB,CAAC;AAWxE,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACvC,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AA6BrC,eAAO,MAAM,kBAAkB,GAC5B,eAAe,aAAa,CAAC,SAAS,CAAC,KAAG,aAAa,CAAC,WAAW,CAAC,CAAC,eAAe,CAkEjF,CAAC"}
|
|
@@ -44,6 +44,7 @@ const buildSignOperation = (signerContext) => ({ account, transaction, deviceId
|
|
|
44
44
|
signature = res.signature;
|
|
45
45
|
encodedSignedCallBlob = Buffer.from(agent_1.Cbor.encode(res.callBody)).toString("hex");
|
|
46
46
|
(0, invariant_1.default)(signature, "[ICP](signOperation) Signature not found");
|
|
47
|
+
const transferRequestIdHex = Buffer.from((0, agent_1.requestIdOf)(unsignedTransaction)).toString("hex");
|
|
47
48
|
o.next({
|
|
48
49
|
type: "device-signature-granted",
|
|
49
50
|
});
|
|
@@ -63,6 +64,7 @@ const buildSignOperation = (signerContext) => ({ account, transaction, deviceId
|
|
|
63
64
|
signature,
|
|
64
65
|
rawData: {
|
|
65
66
|
encodedSignedCallBlob,
|
|
67
|
+
transferRequestIdHex,
|
|
66
68
|
},
|
|
67
69
|
},
|
|
68
70
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"signOperation.js","sourceRoot":"","sources":["../../src/bridge/signOperation.ts"],"names":[],"mappings":";;;;;;AACA,yCAAqC;AAErC,
|
|
1
|
+
{"version":3,"file":"signOperation.js","sourceRoot":"","sources":["../../src/bridge/signOperation.ts"],"names":[],"mappings":"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"}
|
package/lib-es/api/api.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { TransactionWithId } from "@zondax/ledger-live-icp";
|
|
2
2
|
import BigNumber from "bignumber.js";
|
|
3
3
|
export declare const fetchBlockHeight: () => Promise<BigNumber>;
|
|
4
|
-
export declare const broadcastTxn: (payload: Buffer, canisterId: string, type: "call" | "read_state") => Promise<ArrayBuffer
|
|
4
|
+
export declare const broadcastTxn: (payload: Buffer, canisterId: string, type: "call" | "read_state") => Promise<Uint8Array<ArrayBuffer>>;
|
|
5
|
+
export declare const ensureTransferCallAccepted: (syncCallResponse: Uint8Array, transferRequestIdHex: string) => Promise<void>;
|
|
5
6
|
export declare const fetchBalance: (address: string) => Promise<BigNumber>;
|
|
6
7
|
export declare const fetchTxns: (address: string, startBlockHeight: bigint, stopBlockHeight?: bigint) => Promise<TransactionWithId[]>;
|
|
7
8
|
//# sourceMappingURL=api.d.ts.map
|
package/lib-es/api/api.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../src/api/api.ts"],"names":[],"mappings":"AAEA,OAAO,EAQL,iBAAiB,EAClB,MAAM,yBAAyB,CAAC;AAGjC,OAAO,SAAS,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../src/api/api.ts"],"names":[],"mappings":"AAEA,OAAO,EAQL,iBAAiB,EAClB,MAAM,yBAAyB,CAAC;AAGjC,OAAO,SAAS,MAAM,cAAc,CAAC;AAkDrC,eAAO,MAAM,gBAAgB,QAAa,OAAO,CAAC,SAAS,CA0B1D,CAAC;AAEF,eAAO,MAAM,YAAY,GACvB,SAAS,MAAM,EACf,YAAY,MAAM,EAClB,MAAM,MAAM,GAAG,YAAY,qCAgB5B,CAAC;AAEF,eAAO,MAAM,0BAA0B,GACrC,kBAAkB,UAAU,EAC5B,sBAAsB,MAAM,kBA0B7B,CAAC;AAEF,eAAO,MAAM,YAAY,GAAU,SAAS,MAAM,KAAG,OAAO,CAAC,SAAS,CAuBrE,CAAC;AAEF,eAAO,MAAM,SAAS,GACpB,SAAS,MAAM,EACf,kBAAkB,MAAM,EACxB,wBAA2B,KAC1B,OAAO,CAAC,iBAAiB,EAAE,CA6C7B,CAAC"}
|
package/lib-es/api/api.js
CHANGED
|
@@ -1,10 +1,41 @@
|
|
|
1
1
|
import { log } from "@ledgerhq/logs";
|
|
2
2
|
import { ledgerIdlFactory, indexIdlFactory, getCanisterIdlFunc, Principal, encodeCanisterIdlFunc, decodeCanisterIdlFunc, } from "@zondax/ledger-live-icp";
|
|
3
|
-
import { getAgent } from "@zondax/ledger-live-icp/agent";
|
|
3
|
+
import { Certificate, Cbor, getAgent, lookupResultToBuffer } from "@zondax/ledger-live-icp/agent";
|
|
4
4
|
import { fromNullable } from "@zondax/ledger-live-icp/utils";
|
|
5
5
|
import BigNumber from "bignumber.js";
|
|
6
6
|
import invariant from "invariant";
|
|
7
7
|
import { FETCH_TXNS_LIMIT, MAINNET_INDEX_CANISTER_ID, MAINNET_LEDGER_CANISTER_ID, ICP_NETWORK_URL, } from "../consts";
|
|
8
|
+
function toArrayBuffer(view) {
|
|
9
|
+
if (view instanceof ArrayBuffer) {
|
|
10
|
+
return view;
|
|
11
|
+
}
|
|
12
|
+
const copy = new Uint8Array(view.byteLength);
|
|
13
|
+
copy.set(view);
|
|
14
|
+
return copy.buffer;
|
|
15
|
+
}
|
|
16
|
+
function requestIdFromHex(hex) {
|
|
17
|
+
const bytes = Buffer.from(hex, "hex");
|
|
18
|
+
const copy = new Uint8Array(bytes);
|
|
19
|
+
return copy.buffer;
|
|
20
|
+
}
|
|
21
|
+
function throwIfLedgerTransferReplyIsErr(replyBuf) {
|
|
22
|
+
const transferIdlFunc = getCanisterIdlFunc(ledgerIdlFactory, "transfer");
|
|
23
|
+
const decoded = decodeCanisterIdlFunc(transferIdlFunc, replyBuf);
|
|
24
|
+
const out = decoded[0];
|
|
25
|
+
if (out.Err) {
|
|
26
|
+
const message = JSON.stringify(out.Err, (_, v) => (typeof v === "bigint" ? v.toString() : v));
|
|
27
|
+
throw new Error(message);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
async function fetchRootKey() {
|
|
31
|
+
const res = await fetch(`${ICP_NETWORK_URL}/api/v2/status`);
|
|
32
|
+
if (res.status !== 200) {
|
|
33
|
+
throw new Error(`Failed to fetch status: ${await res.text()}`);
|
|
34
|
+
}
|
|
35
|
+
const status = Cbor.decode(await res.arrayBuffer());
|
|
36
|
+
invariant(status.root_key, "[ICP](fetchRootKey) Missing root_key in status response");
|
|
37
|
+
return toArrayBuffer(status.root_key);
|
|
38
|
+
}
|
|
8
39
|
export const fetchBlockHeight = async () => {
|
|
9
40
|
const canisterId = Principal.fromText(MAINNET_LEDGER_CANISTER_ID);
|
|
10
41
|
const queryBlocksRawRequest = {
|
|
@@ -34,9 +65,25 @@ export const broadcastTxn = async (payload, canisterId, type) => {
|
|
|
34
65
|
},
|
|
35
66
|
});
|
|
36
67
|
if (res.status === 200) {
|
|
37
|
-
return await res.arrayBuffer();
|
|
68
|
+
return new Uint8Array(await res.arrayBuffer());
|
|
38
69
|
}
|
|
39
|
-
throw new Error(`Failed to broadcast transaction: ${res.text()}`);
|
|
70
|
+
throw new Error(`Failed to broadcast transaction: ${await res.text()}`);
|
|
71
|
+
};
|
|
72
|
+
export const ensureTransferCallAccepted = async (syncCallResponse, transferRequestIdHex) => {
|
|
73
|
+
const requestId = requestIdFromHex(transferRequestIdHex);
|
|
74
|
+
const canisterId = Principal.fromText(MAINNET_LEDGER_CANISTER_ID);
|
|
75
|
+
const top = Cbor.decode(toArrayBuffer(syncCallResponse));
|
|
76
|
+
invariant(top.status === "replied" && top.certificate, "[ICP](ensureTransferCallAccepted) Decoding failed");
|
|
77
|
+
const rootKey = await fetchRootKey();
|
|
78
|
+
const cert = await Certificate.create({
|
|
79
|
+
certificate: toArrayBuffer(top.certificate),
|
|
80
|
+
rootKey,
|
|
81
|
+
canisterId,
|
|
82
|
+
maxAgeInMinutes: 100,
|
|
83
|
+
});
|
|
84
|
+
const replyBuf = lookupResultToBuffer(cert.lookup(["request_status", requestId, "reply"]));
|
|
85
|
+
invariant(replyBuf, "[ICP](ensureTransferCallAccepted) Reply status not found");
|
|
86
|
+
throwIfLedgerTransferReplyIsErr(replyBuf);
|
|
40
87
|
};
|
|
41
88
|
export const fetchBalance = async (address) => {
|
|
42
89
|
const agent = await getAgent(ICP_NETWORK_URL);
|
package/lib-es/api/api.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api.js","sourceRoot":"","sources":["../../src/api/api.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"api.js","sourceRoot":"","sources":["../../src/api/api.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"broadcast.d.ts","sourceRoot":"","sources":["../../src/bridge/broadcast.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAIrD,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"broadcast.d.ts","sourceRoot":"","sources":["../../src/bridge/broadcast.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAIrD,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAqBvC,eAAO,MAAM,SAAS,EAAE,aAAa,CAAC,WAAW,CAAC,CAAC,WAAW,CAiB7D,CAAC"}
|
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import { log } from "@ledgerhq/logs";
|
|
2
2
|
import invariant from "invariant";
|
|
3
|
-
import { broadcastTxn } from "../api";
|
|
3
|
+
import { broadcastTxn, ensureTransferCallAccepted } from "../api";
|
|
4
4
|
import { MAINNET_LEDGER_CANISTER_ID } from "../consts";
|
|
5
|
-
// Type guard to validate rawData shape
|
|
6
5
|
function isBroadcastRawData(data) {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
6
|
+
if (typeof data !== "object" || data === null) {
|
|
7
|
+
return false;
|
|
8
|
+
}
|
|
9
|
+
return ("encodedSignedCallBlob" in data &&
|
|
10
|
+
typeof data.encodedSignedCallBlob === "string" &&
|
|
11
|
+
"transferRequestIdHex" in data &&
|
|
12
|
+
typeof data.transferRequestIdHex === "string");
|
|
11
13
|
}
|
|
12
14
|
// Main broadcast function for handling Internet Computer transactions
|
|
13
15
|
export const broadcast = async ({ signedOperation: { operation, rawData }, }) => {
|
|
@@ -15,7 +17,8 @@ export const broadcast = async ({ signedOperation: { operation, rawData }, }) =>
|
|
|
15
17
|
// Validate rawData with type guard
|
|
16
18
|
invariant(isBroadcastRawData(rawData), "[ICP](broadcast) Invalid rawData format");
|
|
17
19
|
invariant(operation.extra, "[ICP](broadcast) Missing operation extra");
|
|
18
|
-
await broadcastTxn(Buffer.from(rawData.encodedSignedCallBlob, "hex"), MAINNET_LEDGER_CANISTER_ID, "call");
|
|
20
|
+
const syncCallResponse = await broadcastTxn(Buffer.from(rawData.encodedSignedCallBlob, "hex"), MAINNET_LEDGER_CANISTER_ID, "call");
|
|
21
|
+
await ensureTransferCallAccepted(syncCallResponse, rawData.transferRequestIdHex);
|
|
19
22
|
return operation;
|
|
20
23
|
};
|
|
21
24
|
//# sourceMappingURL=broadcast.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"broadcast.js","sourceRoot":"","sources":["../../src/bridge/broadcast.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,gBAAgB,CAAC;AAErC,OAAO,SAAS,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"broadcast.js","sourceRoot":"","sources":["../../src/bridge/broadcast.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,gBAAgB,CAAC;AAErC,OAAO,SAAS,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,YAAY,EAAE,0BAA0B,EAAE,MAAM,QAAQ,CAAC;AAClE,OAAO,EAAE,0BAA0B,EAAE,MAAM,WAAW,CAAC;AAQvD,SAAS,kBAAkB,CAAC,IAAa;IACvC,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;QAC9C,OAAO,KAAK,CAAC;IACf,CAAC;IAED,OAAO,CACL,uBAAuB,IAAI,IAAI;QAC/B,OAAO,IAAI,CAAC,qBAAqB,KAAK,QAAQ;QAC9C,sBAAsB,IAAI,IAAI;QAC9B,OAAO,IAAI,CAAC,oBAAoB,KAAK,QAAQ,CAC9C,CAAC;AACJ,CAAC;AAED,sEAAsE;AACtE,MAAM,CAAC,MAAM,SAAS,GAA4C,KAAK,EAAE,EACvE,eAAe,EAAE,EAAE,SAAS,EAAE,OAAO,EAAE,GACxC,EAAE,EAAE;IACH,GAAG,CAAC,OAAO,EAAE,+DAA+D,CAAC,CAAC;IAE9E,mCAAmC;IACnC,SAAS,CAAC,kBAAkB,CAAC,OAAO,CAAC,EAAE,yCAAyC,CAAC,CAAC;IAClF,SAAS,CAAC,SAAS,CAAC,KAAK,EAAE,0CAA0C,CAAC,CAAC;IAEvE,MAAM,gBAAgB,GAAG,MAAM,YAAY,CACzC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,qBAAqB,EAAE,KAAK,CAAC,EACjD,0BAA0B,EAC1B,MAAM,CACP,CAAC;IACF,MAAM,0BAA0B,CAAC,gBAAgB,EAAE,OAAO,CAAC,oBAAoB,CAAC,CAAC;IAEjF,OAAO,SAAS,CAAC;AACnB,CAAC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"signOperation.d.ts","sourceRoot":"","sources":["../../src/bridge/signOperation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,0CAA0C,CAAC;AAEzE,OAAO,EAAW,aAAa,EAAY,MAAM,sBAAsB,CAAC;AAWxE,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACvC,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AA6BrC,eAAO,MAAM,kBAAkB,GAC5B,eAAe,aAAa,CAAC,SAAS,CAAC,KAAG,aAAa,CAAC,WAAW,CAAC,CAAC,eAAe,
|
|
1
|
+
{"version":3,"file":"signOperation.d.ts","sourceRoot":"","sources":["../../src/bridge/signOperation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,0CAA0C,CAAC;AAEzE,OAAO,EAAW,aAAa,EAAY,MAAM,sBAAsB,CAAC;AAWxE,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACvC,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AA6BrC,eAAO,MAAM,kBAAkB,GAC5B,eAAe,aAAa,CAAC,SAAS,CAAC,KAAG,aAAa,CAAC,WAAW,CAAC,CAAC,eAAe,CAkEjF,CAAC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { log } from "@ledgerhq/logs";
|
|
2
|
-
import { Cbor } from "@zondax/ledger-live-icp/agent";
|
|
2
|
+
import { Cbor, requestIdOf } from "@zondax/ledger-live-icp/agent";
|
|
3
3
|
import { createUnsignedSendTransaction, hashTransaction, pubkeyToDer, } from "@zondax/ledger-live-icp/utils";
|
|
4
4
|
import invariant from "invariant";
|
|
5
5
|
import { Observable } from "rxjs";
|
|
@@ -38,6 +38,7 @@ export const buildSignOperation = (signerContext) => ({ account, transaction, de
|
|
|
38
38
|
signature = res.signature;
|
|
39
39
|
encodedSignedCallBlob = Buffer.from(Cbor.encode(res.callBody)).toString("hex");
|
|
40
40
|
invariant(signature, "[ICP](signOperation) Signature not found");
|
|
41
|
+
const transferRequestIdHex = Buffer.from(requestIdOf(unsignedTransaction)).toString("hex");
|
|
41
42
|
o.next({
|
|
42
43
|
type: "device-signature-granted",
|
|
43
44
|
});
|
|
@@ -57,6 +58,7 @@ export const buildSignOperation = (signerContext) => ({ account, transaction, de
|
|
|
57
58
|
signature,
|
|
58
59
|
rawData: {
|
|
59
60
|
encodedSignedCallBlob,
|
|
61
|
+
transferRequestIdHex,
|
|
60
62
|
},
|
|
61
63
|
},
|
|
62
64
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"signOperation.js","sourceRoot":"","sources":["../../src/bridge/signOperation.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,GAAG,EAAE,MAAM,gBAAgB,CAAC;AAErC,OAAO,EAAE,IAAI,EAAE,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"signOperation.js","sourceRoot":"","sources":["../../src/bridge/signOperation.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ledgerhq/coin-internet_computer",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.22.0",
|
|
4
4
|
"description": "Ledger Internet Computer integration",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"Ledger",
|
|
@@ -99,14 +99,18 @@
|
|
|
99
99
|
"invariant": "^2.2.2",
|
|
100
100
|
"lodash": "^4.17.21",
|
|
101
101
|
"rxjs": "7.8.2",
|
|
102
|
-
"@ledgerhq/cryptoassets": "^13.
|
|
102
|
+
"@ledgerhq/cryptoassets": "^13.47.0",
|
|
103
103
|
"@ledgerhq/devices": "8.14.2",
|
|
104
|
-
"@ledgerhq/errors": "^6.
|
|
105
|
-
"@ledgerhq/ledger-wallet-framework": "^1.
|
|
104
|
+
"@ledgerhq/errors": "^6.35.0",
|
|
105
|
+
"@ledgerhq/ledger-wallet-framework": "^1.4.0",
|
|
106
106
|
"@ledgerhq/logs": "^6.17.0",
|
|
107
|
-
"@ledgerhq/types-live": "^6.
|
|
107
|
+
"@ledgerhq/types-live": "^6.107.0"
|
|
108
108
|
},
|
|
109
109
|
"devDependencies": {
|
|
110
|
+
"@dfinity/agent": "2.4.1",
|
|
111
|
+
"@dfinity/candid": "2.4.1",
|
|
112
|
+
"@dfinity/identity-secp256k1": "2.4.1",
|
|
113
|
+
"@dfinity/principal": "2.4.1",
|
|
110
114
|
"@swc/core": "1.15.11",
|
|
111
115
|
"@swc/jest": "0.2.39",
|
|
112
116
|
"@types/invariant": "^2.2.2",
|
|
@@ -130,6 +134,7 @@
|
|
|
130
134
|
"lint": "oxlint src",
|
|
131
135
|
"lint:fix": "oxfmt src && oxlint src --fix --quiet",
|
|
132
136
|
"test": "jest",
|
|
137
|
+
"test-integ": "jest --config=jest.integ.config.js",
|
|
133
138
|
"unimported": "unimported",
|
|
134
139
|
"format": "oxfmt src",
|
|
135
140
|
"format:check": "oxfmt src --check"
|
package/src/api/api.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
import type { RequestId } from "@dfinity/agent";
|
|
1
2
|
import { log } from "@ledgerhq/logs";
|
|
2
|
-
|
|
3
3
|
import {
|
|
4
4
|
ledgerIdlFactory,
|
|
5
5
|
indexIdlFactory,
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
GetAccountIdentifierTransactionsResponse,
|
|
11
11
|
TransactionWithId,
|
|
12
12
|
} from "@zondax/ledger-live-icp";
|
|
13
|
-
import { getAgent } from "@zondax/ledger-live-icp/agent";
|
|
13
|
+
import { Certificate, Cbor, getAgent, lookupResultToBuffer } from "@zondax/ledger-live-icp/agent";
|
|
14
14
|
import { fromNullable } from "@zondax/ledger-live-icp/utils";
|
|
15
15
|
import BigNumber from "bignumber.js";
|
|
16
16
|
import invariant from "invariant";
|
|
@@ -21,6 +21,47 @@ import {
|
|
|
21
21
|
ICP_NETWORK_URL,
|
|
22
22
|
} from "../consts";
|
|
23
23
|
|
|
24
|
+
function toArrayBuffer(view: ArrayBuffer | Uint8Array): ArrayBuffer {
|
|
25
|
+
if (view instanceof ArrayBuffer) {
|
|
26
|
+
return view;
|
|
27
|
+
}
|
|
28
|
+
const copy = new Uint8Array(view.byteLength);
|
|
29
|
+
copy.set(view);
|
|
30
|
+
return copy.buffer;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function requestIdFromHex(hex: string): RequestId {
|
|
34
|
+
const bytes = Buffer.from(hex, "hex");
|
|
35
|
+
const copy = new Uint8Array(bytes);
|
|
36
|
+
return copy.buffer as RequestId;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function throwIfLedgerTransferReplyIsErr(replyBuf: ArrayBuffer) {
|
|
40
|
+
const transferIdlFunc = getCanisterIdlFunc(ledgerIdlFactory, "transfer");
|
|
41
|
+
const decoded = decodeCanisterIdlFunc<[{ Err?: unknown; Ok?: unknown }]>(
|
|
42
|
+
transferIdlFunc,
|
|
43
|
+
replyBuf,
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
const out = decoded[0];
|
|
47
|
+
if (out.Err) {
|
|
48
|
+
const message = JSON.stringify(out.Err, (_, v) => (typeof v === "bigint" ? v.toString() : v));
|
|
49
|
+
throw new Error(message);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
async function fetchRootKey(): Promise<ArrayBuffer> {
|
|
54
|
+
const res = await fetch(`${ICP_NETWORK_URL}/api/v2/status`);
|
|
55
|
+
if (res.status !== 200) {
|
|
56
|
+
throw new Error(`Failed to fetch status: ${await res.text()}`);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const status = Cbor.decode<{ root_key?: ArrayBuffer | Uint8Array }>(await res.arrayBuffer());
|
|
60
|
+
invariant(status.root_key, "[ICP](fetchRootKey) Missing root_key in status response");
|
|
61
|
+
|
|
62
|
+
return toArrayBuffer(status.root_key);
|
|
63
|
+
}
|
|
64
|
+
|
|
24
65
|
export const fetchBlockHeight = async (): Promise<BigNumber> => {
|
|
25
66
|
const canisterId = Principal.fromText(MAINNET_LEDGER_CANISTER_ID);
|
|
26
67
|
const queryBlocksRawRequest = {
|
|
@@ -64,10 +105,40 @@ export const broadcastTxn = async (
|
|
|
64
105
|
});
|
|
65
106
|
|
|
66
107
|
if (res.status === 200) {
|
|
67
|
-
return await res.arrayBuffer();
|
|
108
|
+
return new Uint8Array(await res.arrayBuffer());
|
|
68
109
|
}
|
|
69
110
|
|
|
70
|
-
throw new Error(`Failed to broadcast transaction: ${res.text()}`);
|
|
111
|
+
throw new Error(`Failed to broadcast transaction: ${await res.text()}`);
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
export const ensureTransferCallAccepted = async (
|
|
115
|
+
syncCallResponse: Uint8Array,
|
|
116
|
+
transferRequestIdHex: string,
|
|
117
|
+
) => {
|
|
118
|
+
const requestId = requestIdFromHex(transferRequestIdHex);
|
|
119
|
+
const canisterId = Principal.fromText(MAINNET_LEDGER_CANISTER_ID);
|
|
120
|
+
const top = Cbor.decode<{
|
|
121
|
+
status?: string;
|
|
122
|
+
certificate?: ArrayBuffer | Uint8Array;
|
|
123
|
+
}>(toArrayBuffer(syncCallResponse));
|
|
124
|
+
|
|
125
|
+
invariant(
|
|
126
|
+
top.status === "replied" && top.certificate,
|
|
127
|
+
"[ICP](ensureTransferCallAccepted) Decoding failed",
|
|
128
|
+
);
|
|
129
|
+
|
|
130
|
+
const rootKey = await fetchRootKey();
|
|
131
|
+
const cert = await Certificate.create({
|
|
132
|
+
certificate: toArrayBuffer(top.certificate),
|
|
133
|
+
rootKey,
|
|
134
|
+
canisterId,
|
|
135
|
+
maxAgeInMinutes: 100,
|
|
136
|
+
});
|
|
137
|
+
const replyBuf = lookupResultToBuffer(cert.lookup(["request_status", requestId, "reply"]));
|
|
138
|
+
|
|
139
|
+
invariant(replyBuf, "[ICP](ensureTransferCallAccepted) Reply status not found");
|
|
140
|
+
|
|
141
|
+
throwIfLedgerTransferReplyIsErr(replyBuf);
|
|
71
142
|
};
|
|
72
143
|
|
|
73
144
|
export const fetchBalance = async (address: string): Promise<BigNumber> => {
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { Secp256k1KeyIdentity } from "@dfinity/identity-secp256k1";
|
|
2
|
+
import { BigNumber } from "bignumber.js";
|
|
3
|
+
import { Cbor, concat, requestIdOf } from "@zondax/ledger-live-icp/agent";
|
|
4
|
+
import {
|
|
5
|
+
createUnsignedSendTransaction,
|
|
6
|
+
deriveAddressFromPubkey,
|
|
7
|
+
pubkeyToDer,
|
|
8
|
+
} from "@zondax/ledger-live-icp/utils";
|
|
9
|
+
import { broadcast } from "./broadcast";
|
|
10
|
+
import { ICP_FEES } from "../consts";
|
|
11
|
+
|
|
12
|
+
describe("Broadcast", () => {
|
|
13
|
+
it("throws on insufficient funds", async () => {
|
|
14
|
+
const identity = Secp256k1KeyIdentity.generate();
|
|
15
|
+
const xpub = Buffer.from(new Uint8Array(identity.getPublicKey().toRaw())).toString("hex");
|
|
16
|
+
const freshAddress = deriveAddressFromPubkey(xpub);
|
|
17
|
+
const transaction = {
|
|
18
|
+
amount: new BigNumber(100_000_000),
|
|
19
|
+
recipient: freshAddress,
|
|
20
|
+
fees: new BigNumber(ICP_FEES),
|
|
21
|
+
} as any;
|
|
22
|
+
const { unsignedTransaction } = createUnsignedSendTransaction(transaction, xpub);
|
|
23
|
+
const domainSeparator = new TextEncoder().encode("\x0Aic-request");
|
|
24
|
+
const rid = requestIdOf(unsignedTransaction as Record<string, unknown>);
|
|
25
|
+
const domainBuf = domainSeparator.buffer.slice(
|
|
26
|
+
domainSeparator.byteOffset,
|
|
27
|
+
domainSeparator.byteOffset + domainSeparator.byteLength,
|
|
28
|
+
) as ArrayBuffer;
|
|
29
|
+
const challenge = new Uint8Array(concat(domainBuf, rid));
|
|
30
|
+
const sig = await identity.sign(
|
|
31
|
+
challenge.buffer.slice(challenge.byteOffset, challenge.byteOffset + challenge.byteLength),
|
|
32
|
+
);
|
|
33
|
+
const signatureRS = Buffer.from(sig);
|
|
34
|
+
const callBody = {
|
|
35
|
+
content: unsignedTransaction,
|
|
36
|
+
sender_pubkey: pubkeyToDer(xpub),
|
|
37
|
+
sender_sig: signatureRS,
|
|
38
|
+
};
|
|
39
|
+
const encodedSignedCallBlob = Buffer.from(Cbor.encode(callBody)).toString("hex");
|
|
40
|
+
const transferRequestIdHex = Buffer.from(requestIdOf(unsignedTransaction)).toString("hex");
|
|
41
|
+
|
|
42
|
+
await expect(
|
|
43
|
+
broadcast({
|
|
44
|
+
signedOperation: {
|
|
45
|
+
operation: { extra: { memo: transaction.memo } },
|
|
46
|
+
rawData: { encodedSignedCallBlob, transferRequestIdHex },
|
|
47
|
+
},
|
|
48
|
+
} as any),
|
|
49
|
+
).rejects.toThrow(/InsufficientFunds/);
|
|
50
|
+
});
|
|
51
|
+
});
|
package/src/bridge/broadcast.ts
CHANGED
|
@@ -1,22 +1,25 @@
|
|
|
1
1
|
import { log } from "@ledgerhq/logs";
|
|
2
2
|
import { AccountBridge } from "@ledgerhq/types-live";
|
|
3
3
|
import invariant from "invariant";
|
|
4
|
-
import { broadcastTxn } from "../api";
|
|
4
|
+
import { broadcastTxn, ensureTransferCallAccepted } from "../api";
|
|
5
5
|
import { MAINNET_LEDGER_CANISTER_ID } from "../consts";
|
|
6
6
|
import { Transaction } from "../types";
|
|
7
7
|
|
|
8
|
-
// Interface to structure raw data for broadcasting transactions
|
|
9
8
|
interface BroadcastRawData {
|
|
10
9
|
encodedSignedCallBlob: string;
|
|
10
|
+
transferRequestIdHex: string;
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
// Type guard to validate rawData shape
|
|
14
13
|
function isBroadcastRawData(data: unknown): data is BroadcastRawData {
|
|
14
|
+
if (typeof data !== "object" || data === null) {
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
|
|
15
18
|
return (
|
|
16
|
-
typeof data === "object" &&
|
|
17
|
-
data !== null &&
|
|
18
19
|
"encodedSignedCallBlob" in data &&
|
|
19
|
-
typeof
|
|
20
|
+
typeof data.encodedSignedCallBlob === "string" &&
|
|
21
|
+
"transferRequestIdHex" in data &&
|
|
22
|
+
typeof data.transferRequestIdHex === "string"
|
|
20
23
|
);
|
|
21
24
|
}
|
|
22
25
|
|
|
@@ -30,11 +33,12 @@ export const broadcast: AccountBridge<Transaction>["broadcast"] = async ({
|
|
|
30
33
|
invariant(isBroadcastRawData(rawData), "[ICP](broadcast) Invalid rawData format");
|
|
31
34
|
invariant(operation.extra, "[ICP](broadcast) Missing operation extra");
|
|
32
35
|
|
|
33
|
-
await broadcastTxn(
|
|
36
|
+
const syncCallResponse = await broadcastTxn(
|
|
34
37
|
Buffer.from(rawData.encodedSignedCallBlob, "hex"),
|
|
35
38
|
MAINNET_LEDGER_CANISTER_ID,
|
|
36
39
|
"call",
|
|
37
40
|
);
|
|
41
|
+
await ensureTransferCallAccepted(syncCallResponse, rawData.transferRequestIdHex);
|
|
38
42
|
|
|
39
43
|
return operation;
|
|
40
44
|
};
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { broadcast } from "./broadcast";
|
|
2
|
+
import { MAINNET_LEDGER_CANISTER_ID } from "../consts";
|
|
3
|
+
import { broadcastTxn, ensureTransferCallAccepted } from "../api";
|
|
4
|
+
|
|
5
|
+
jest.mock("../api", () => ({
|
|
6
|
+
broadcastTxn: jest.fn(),
|
|
7
|
+
ensureTransferCallAccepted: jest.fn(),
|
|
8
|
+
}));
|
|
9
|
+
|
|
10
|
+
describe("broadcast", () => {
|
|
11
|
+
beforeEach(() => {
|
|
12
|
+
jest.mocked(broadcastTxn).mockReset();
|
|
13
|
+
jest.mocked(ensureTransferCallAccepted).mockReset();
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
it("returns the operation when transfer reply is Ok", async () => {
|
|
17
|
+
jest.mocked(broadcastTxn).mockResolvedValue(new Uint8Array([1, 2, 3]));
|
|
18
|
+
jest.mocked(ensureTransferCallAccepted).mockResolvedValue(undefined);
|
|
19
|
+
|
|
20
|
+
const result = await broadcast({
|
|
21
|
+
signedOperation: {
|
|
22
|
+
operation: { extra: { memo: 0 } },
|
|
23
|
+
rawData: { encodedSignedCallBlob: "00", transferRequestIdHex: "ab".repeat(32) },
|
|
24
|
+
},
|
|
25
|
+
} as any);
|
|
26
|
+
|
|
27
|
+
expect(result).toEqual({ extra: { memo: 0 } });
|
|
28
|
+
expect(broadcastTxn).toHaveBeenCalledTimes(1);
|
|
29
|
+
expect(broadcastTxn).toHaveBeenCalledWith(
|
|
30
|
+
Buffer.from("00", "hex"),
|
|
31
|
+
MAINNET_LEDGER_CANISTER_ID,
|
|
32
|
+
"call",
|
|
33
|
+
);
|
|
34
|
+
expect(ensureTransferCallAccepted).toHaveBeenCalledTimes(1);
|
|
35
|
+
expect(ensureTransferCallAccepted).toHaveBeenCalledWith(
|
|
36
|
+
new Uint8Array([1, 2, 3]),
|
|
37
|
+
"ab".repeat(32),
|
|
38
|
+
);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it("rejects when transfer reply is Err (e.g. insufficient funds)", async () => {
|
|
42
|
+
jest.mocked(broadcastTxn).mockResolvedValue(new Uint8Array([1, 2, 3]));
|
|
43
|
+
jest
|
|
44
|
+
.mocked(ensureTransferCallAccepted)
|
|
45
|
+
.mockRejectedValue(
|
|
46
|
+
new Error(
|
|
47
|
+
'Failed to broadcast transaction: {"InsufficientFunds":{"balance":{"e8s":"0"},"requested":{"e8s":"1"}}}',
|
|
48
|
+
),
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
await expect(
|
|
52
|
+
broadcast({
|
|
53
|
+
account: {} as never,
|
|
54
|
+
signedOperation: {
|
|
55
|
+
operation: { extra: { memo: 0 } },
|
|
56
|
+
rawData: { encodedSignedCallBlob: "00", transferRequestIdHex: "ab".repeat(32) },
|
|
57
|
+
},
|
|
58
|
+
} as any),
|
|
59
|
+
).rejects.toThrow(/InsufficientFunds/);
|
|
60
|
+
|
|
61
|
+
expect(broadcastTxn).toHaveBeenCalledTimes(1);
|
|
62
|
+
expect(ensureTransferCallAccepted).toHaveBeenCalledWith(
|
|
63
|
+
new Uint8Array([1, 2, 3]),
|
|
64
|
+
"ab".repeat(32),
|
|
65
|
+
);
|
|
66
|
+
});
|
|
67
|
+
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { SignerContext } from "@ledgerhq/ledger-wallet-framework/signer";
|
|
2
2
|
import { log } from "@ledgerhq/logs";
|
|
3
3
|
import { Account, AccountBridge, DeviceId } from "@ledgerhq/types-live";
|
|
4
|
-
import { Cbor } from "@zondax/ledger-live-icp/agent";
|
|
4
|
+
import { Cbor, requestIdOf } from "@zondax/ledger-live-icp/agent";
|
|
5
5
|
import {
|
|
6
6
|
UnsignedTransaction,
|
|
7
7
|
createUnsignedSendTransaction,
|
|
@@ -75,6 +75,7 @@ export const buildSignOperation =
|
|
|
75
75
|
signature = res.signature;
|
|
76
76
|
encodedSignedCallBlob = Buffer.from(Cbor.encode(res.callBody)).toString("hex");
|
|
77
77
|
invariant(signature, "[ICP](signOperation) Signature not found");
|
|
78
|
+
const transferRequestIdHex = Buffer.from(requestIdOf(unsignedTransaction)).toString("hex");
|
|
78
79
|
|
|
79
80
|
o.next({
|
|
80
81
|
type: "device-signature-granted",
|
|
@@ -97,6 +98,7 @@ export const buildSignOperation =
|
|
|
97
98
|
signature,
|
|
98
99
|
rawData: {
|
|
99
100
|
encodedSignedCallBlob,
|
|
101
|
+
transferRequestIdHex,
|
|
100
102
|
},
|
|
101
103
|
},
|
|
102
104
|
});
|