@ledgerhq/coin-internet_computer 1.9.0-nightly.6 → 1.9.0-nightly.7

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 (106) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/CHANGELOG.md +13 -0
  3. package/lib/api/api.d.ts +6 -11
  4. package/lib/api/api.d.ts.map +1 -1
  5. package/lib/api/api.js +84 -64
  6. package/lib/api/api.js.map +1 -1
  7. package/lib/bridge/bridgeHelpers/account.d.ts.map +1 -1
  8. package/lib/bridge/bridgeHelpers/account.js +52 -33
  9. package/lib/bridge/bridgeHelpers/account.js.map +1 -1
  10. package/lib/bridge/bridgeHelpers/addresses.d.ts +0 -6
  11. package/lib/bridge/bridgeHelpers/addresses.d.ts.map +1 -1
  12. package/lib/bridge/bridgeHelpers/addresses.js +1 -29
  13. package/lib/bridge/bridgeHelpers/addresses.js.map +1 -1
  14. package/lib/bridge/broadcast.d.ts.map +1 -1
  15. package/lib/bridge/broadcast.js +22 -6
  16. package/lib/bridge/broadcast.js.map +1 -1
  17. package/lib/bridge/getTransactionStatus.d.ts.map +1 -1
  18. package/lib/bridge/getTransactionStatus.js +4 -3
  19. package/lib/bridge/getTransactionStatus.js.map +1 -1
  20. package/lib/bridge/prepareTransaction.d.ts.map +1 -1
  21. package/lib/bridge/prepareTransaction.js +2 -1
  22. package/lib/bridge/prepareTransaction.js.map +1 -1
  23. package/lib/bridge/signOperation.d.ts +2 -2
  24. package/lib/bridge/signOperation.d.ts.map +1 -1
  25. package/lib/bridge/signOperation.js +44 -13
  26. package/lib/bridge/signOperation.js.map +1 -1
  27. package/lib/consts.d.ts +2 -0
  28. package/lib/consts.d.ts.map +1 -1
  29. package/lib/consts.js +8 -1
  30. package/lib/consts.js.map +1 -1
  31. package/lib/hw-signMessage.d.ts.map +1 -1
  32. package/lib/hw-signMessage.js +1 -2
  33. package/lib/hw-signMessage.js.map +1 -1
  34. package/lib/types/signer.d.ts +1 -1
  35. package/lib/types/signer.d.ts.map +1 -1
  36. package/lib-es/api/api.d.ts +6 -11
  37. package/lib-es/api/api.d.ts.map +1 -1
  38. package/lib-es/api/api.js +81 -60
  39. package/lib-es/api/api.js.map +1 -1
  40. package/lib-es/bridge/bridgeHelpers/account.d.ts.map +1 -1
  41. package/lib-es/bridge/bridgeHelpers/account.js +52 -33
  42. package/lib-es/bridge/bridgeHelpers/account.js.map +1 -1
  43. package/lib-es/bridge/bridgeHelpers/addresses.d.ts +0 -6
  44. package/lib-es/bridge/bridgeHelpers/addresses.d.ts.map +1 -1
  45. package/lib-es/bridge/bridgeHelpers/addresses.js +0 -23
  46. package/lib-es/bridge/bridgeHelpers/addresses.js.map +1 -1
  47. package/lib-es/bridge/broadcast.d.ts.map +1 -1
  48. package/lib-es/bridge/broadcast.js +19 -6
  49. package/lib-es/bridge/broadcast.js.map +1 -1
  50. package/lib-es/bridge/getTransactionStatus.d.ts.map +1 -1
  51. package/lib-es/bridge/getTransactionStatus.js +2 -1
  52. package/lib-es/bridge/getTransactionStatus.js.map +1 -1
  53. package/lib-es/bridge/prepareTransaction.d.ts.map +1 -1
  54. package/lib-es/bridge/prepareTransaction.js +2 -1
  55. package/lib-es/bridge/prepareTransaction.js.map +1 -1
  56. package/lib-es/bridge/signOperation.d.ts +2 -2
  57. package/lib-es/bridge/signOperation.d.ts.map +1 -1
  58. package/lib-es/bridge/signOperation.js +41 -13
  59. package/lib-es/bridge/signOperation.js.map +1 -1
  60. package/lib-es/consts.d.ts +2 -0
  61. package/lib-es/consts.d.ts.map +1 -1
  62. package/lib-es/consts.js +3 -0
  63. package/lib-es/consts.js.map +1 -1
  64. package/lib-es/hw-signMessage.d.ts.map +1 -1
  65. package/lib-es/hw-signMessage.js +1 -2
  66. package/lib-es/hw-signMessage.js.map +1 -1
  67. package/lib-es/types/signer.d.ts +1 -1
  68. package/lib-es/types/signer.d.ts.map +1 -1
  69. package/package.json +5 -11
  70. package/src/api/api.ts +126 -71
  71. package/src/bridge/bridgeHelpers/account.ts +70 -43
  72. package/src/bridge/bridgeHelpers/addresses.ts +0 -25
  73. package/src/bridge/broadcast.ts +31 -6
  74. package/src/bridge/getTransactionStatus.ts +2 -1
  75. package/src/bridge/prepareTransaction.ts +2 -1
  76. package/src/bridge/signOperation.ts +68 -18
  77. package/src/consts.ts +10 -0
  78. package/src/hw-signMessage.ts +1 -6
  79. package/src/types/signer.ts +1 -1
  80. package/lib/bridge/bridgeHelpers/icpRosetta/index.d.ts +0 -30
  81. package/lib/bridge/bridgeHelpers/icpRosetta/index.d.ts.map +0 -1
  82. package/lib/bridge/bridgeHelpers/icpRosetta/index.js +0 -88
  83. package/lib/bridge/bridgeHelpers/icpRosetta/index.js.map +0 -1
  84. package/lib/bridge/bridgeHelpers/icpRosetta/types.d.ts +0 -145
  85. package/lib/bridge/bridgeHelpers/icpRosetta/types.d.ts.map +0 -1
  86. package/lib/bridge/bridgeHelpers/icpRosetta/types.js +0 -3
  87. package/lib/bridge/bridgeHelpers/icpRosetta/types.js.map +0 -1
  88. package/lib/bridge/bridgeHelpers/icpRosetta/utils.d.ts +0 -17
  89. package/lib/bridge/bridgeHelpers/icpRosetta/utils.d.ts.map +0 -1
  90. package/lib/bridge/bridgeHelpers/icpRosetta/utils.js +0 -155
  91. package/lib/bridge/bridgeHelpers/icpRosetta/utils.js.map +0 -1
  92. package/lib-es/bridge/bridgeHelpers/icpRosetta/index.d.ts +0 -30
  93. package/lib-es/bridge/bridgeHelpers/icpRosetta/index.d.ts.map +0 -1
  94. package/lib-es/bridge/bridgeHelpers/icpRosetta/index.js +0 -76
  95. package/lib-es/bridge/bridgeHelpers/icpRosetta/index.js.map +0 -1
  96. package/lib-es/bridge/bridgeHelpers/icpRosetta/types.d.ts +0 -145
  97. package/lib-es/bridge/bridgeHelpers/icpRosetta/types.d.ts.map +0 -1
  98. package/lib-es/bridge/bridgeHelpers/icpRosetta/types.js +0 -2
  99. package/lib-es/bridge/bridgeHelpers/icpRosetta/types.js.map +0 -1
  100. package/lib-es/bridge/bridgeHelpers/icpRosetta/utils.d.ts +0 -17
  101. package/lib-es/bridge/bridgeHelpers/icpRosetta/utils.d.ts.map +0 -1
  102. package/lib-es/bridge/bridgeHelpers/icpRosetta/utils.js +0 -123
  103. package/lib-es/bridge/bridgeHelpers/icpRosetta/utils.js.map +0 -1
  104. package/src/bridge/bridgeHelpers/icpRosetta/index.ts +0 -154
  105. package/src/bridge/bridgeHelpers/icpRosetta/types.ts +0 -166
  106. package/src/bridge/bridgeHelpers/icpRosetta/utils.ts +0 -151
@@ -1,16 +1,19 @@
1
1
  import type { GetAccountShape } from "@ledgerhq/coin-framework/bridge/jsHelpers";
2
2
  import { decodeAccountId, encodeAccountId } from "@ledgerhq/coin-framework/account/index";
3
- import { fetchBalances, fetchBlockHeight, fetchTxns } from "../../api";
3
+ import { fetchBalance, fetchBlockHeight, fetchTxns } from "../../api";
4
4
  import flatMap from "lodash/flatMap";
5
- import { Account } from "@ledgerhq/types-live";
5
+ import { Account, OperationType } from "@ledgerhq/types-live";
6
6
  import BigNumber from "bignumber.js";
7
- import { ICPRosettaGetTxnsHistoryResponse } from "./icpRosetta/types";
8
7
  import { ICP_FEES } from "../../consts";
9
8
  import { encodeOperationId } from "@ledgerhq/coin-framework/operation";
10
9
  import { normalizeEpochTimestamp } from "../../common-logic/utils";
11
10
  import { InternetComputerOperation } from "../../types";
12
11
  import invariant from "invariant";
13
- import { deriveAddressFromPubkey } from "./icpRosetta";
12
+ import {
13
+ deriveAddressFromPubkey,
14
+ hashTransaction,
15
+ TransactionWithId,
16
+ } from "@zondax/ledger-live-icp";
14
17
 
15
18
  export const getAccountShape: GetAccountShape = async info => {
16
19
  const { currency, derivationMode, rest = {}, initialAccount } = info;
@@ -32,17 +35,23 @@ export const getAccountShape: GetAccountShape = async info => {
32
35
  // log("debug", `Generation account shape for ${address}`);
33
36
 
34
37
  const blockHeight = await fetchBlockHeight();
35
- const balanceResp = await fetchBalances(address);
36
- const balance = balanceResp.balances[0];
38
+ const balance = await fetchBalance(address);
39
+ const txns = await fetchTxns(
40
+ address,
41
+ BigInt(blockHeight.toString()),
42
+ initialAccount ? BigInt(initialAccount.blockHeight.toString()) : undefined,
43
+ );
37
44
 
38
- const txns = await fetchTxns(address);
39
45
  const result: Partial<Account> = {
40
46
  id: accountId,
41
- balance: BigNumber(balance.value),
42
- spendableBalance: BigNumber(balance.value),
43
- operations: flatMap(txns.transactions.reverse(), mapTxToOps(accountId, address)),
44
- blockHeight: blockHeight.current_block_identifier.index,
45
- operationsCount: txns.transactions.length,
47
+ balance,
48
+ spendableBalance: balance,
49
+ operations: flatMap<TransactionWithId, InternetComputerOperation>(
50
+ txns,
51
+ mapTxToOps(accountId, address),
52
+ ),
53
+ blockHeight: blockHeight.toNumber(),
54
+ operationsCount: (initialAccount?.operations.length ?? 0) + txns.length,
46
55
  xpub: publicKey,
47
56
  };
48
57
 
@@ -59,47 +68,65 @@ function reconciliatePublicKey(publicKey?: string, initialAccount?: Account): st
59
68
  }
60
69
 
61
70
  const mapTxToOps = (accountId: string, address: string, fee = ICP_FEES) => {
62
- return (
63
- txInfo: ICPRosettaGetTxnsHistoryResponse["transactions"][0],
64
- ): InternetComputerOperation[] => {
71
+ return (txInfo: TransactionWithId): InternetComputerOperation[] => {
72
+ const { transaction: txn } = txInfo;
65
73
  const ops: InternetComputerOperation[] = [];
66
- const ownerOperation = txInfo.transaction.operations.find(
67
- cur => cur.account.address === address,
68
- );
69
- const counterOperation = txInfo.transaction.operations.find(
70
- cur => cur.account.address !== address,
71
- );
72
-
73
- if (!ownerOperation || !counterOperation) return ops;
74
-
75
- const timeStamp = txInfo.transaction.metadata.timestamp;
76
- const amount = BigNumber(ownerOperation.amount.value);
77
- const hash = txInfo.transaction.transaction_identifier.hash;
78
- const fromAccount = amount.isPositive()
79
- ? counterOperation.account.address
80
- : ownerOperation.account.address;
81
- const toAccount = amount.isNegative()
82
- ? counterOperation.account.address
83
- : ownerOperation.account.address;
84
- const memo = txInfo.transaction.metadata.memo.toString();
85
- const blockHeight = txInfo.transaction.metadata.block_height;
74
+
75
+ if (txn.operation === undefined) {
76
+ return [];
77
+ }
78
+
79
+ if ("Transfer" in txn.operation === undefined) {
80
+ return [];
81
+ }
82
+
83
+ const timeStamp = txn.timestamp[0]?.timestamp_nanos ?? Date.now();
84
+ let amount = BigNumber(0);
85
+ let fromAccount = "";
86
+ let toAccount = "";
87
+ let hash = "";
88
+ if ("Transfer" in txn.operation) {
89
+ amount = BigNumber(txn.operation.Transfer.amount.e8s.toString());
90
+ fromAccount = txn.operation.Transfer.from;
91
+ toAccount = txn.operation.Transfer.to;
92
+ hash = hashTransaction({
93
+ from: fromAccount,
94
+ to: toAccount,
95
+ amount: txn.operation.Transfer.amount.e8s,
96
+ fee: txn.operation.Transfer.fee.e8s,
97
+ memo: txn.memo,
98
+ created_at_time: txn.created_at_time[0]?.timestamp_nanos ?? BigInt(0),
99
+ });
100
+ }
101
+
102
+ const blockHeight = Number(txInfo.id);
103
+ const blockHash = "";
104
+
105
+ const memo = txInfo.transaction.memo.toString();
86
106
 
87
107
  const date = new Date(normalizeEpochTimestamp(timeStamp.toString()));
88
108
  const value = amount.abs();
89
109
  const feeToUse = BigNumber(fee);
90
110
 
91
- const isSending = amount.isNegative();
92
- const isReceiving = amount.isPositive();
111
+ const isSending = address === fromAccount;
112
+ const isReceiving = address === toAccount;
113
+
114
+ let type: OperationType;
115
+ if (isSending) {
116
+ type = "OUT";
117
+ } else {
118
+ type = "IN";
119
+ }
93
120
 
94
121
  if (isSending) {
95
122
  ops.push({
96
- id: encodeOperationId(accountId, hash, "OUT"),
123
+ id: encodeOperationId(accountId, hash, type),
97
124
  hash,
98
- type: "OUT",
125
+ type,
99
126
  value: value.plus(feeToUse),
100
127
  fee: feeToUse,
101
128
  blockHeight,
102
- blockHash: null,
129
+ blockHash,
103
130
  accountId,
104
131
  senders: [fromAccount],
105
132
  recipients: [toAccount],
@@ -112,13 +139,13 @@ const mapTxToOps = (accountId: string, address: string, fee = ICP_FEES) => {
112
139
 
113
140
  if (isReceiving) {
114
141
  ops.push({
115
- id: encodeOperationId(accountId, hash, "IN"),
142
+ id: encodeOperationId(accountId, hash, type),
116
143
  hash,
117
- type: "IN",
144
+ type,
118
145
  value,
119
146
  fee: feeToUse,
120
147
  blockHeight,
121
- blockHash: null,
148
+ blockHash,
122
149
  accountId,
123
150
  senders: [fromAccount],
124
151
  recipients: [toAccount],
@@ -1,8 +1,4 @@
1
- import { log } from "@ledgerhq/logs";
2
1
  import { Account } from "@ledgerhq/types-live";
3
- import BigNumber from "bignumber.js";
4
- import { MAX_MEMO_VALUE } from "../../consts";
5
- import { fetchBalances } from "../../api";
6
2
 
7
3
  export const getAddress = (
8
4
  a: Account,
@@ -10,24 +6,3 @@ export const getAddress = (
10
6
  address: string;
11
7
  derivationPath: string;
12
8
  } => ({ address: a.freshAddress, derivationPath: a.freshAddressPath });
13
-
14
- export async function validateAddress(address: string): Promise<{ isValid: boolean }> {
15
- try {
16
- const res = await fetchBalances(address);
17
- if (!res.balances) throw Error(res.details?.error_message);
18
- return { isValid: true };
19
- } catch (e: any) {
20
- log("error", e.message ?? "Failed to validate address");
21
- return { isValid: false };
22
- }
23
- }
24
-
25
- export function validateMemo(memo?: string): { isValid: boolean } {
26
- const res = BigNumber(memo ?? 0);
27
-
28
- if (res.isNaN() || res.lt(0) || res.gt(BigNumber(MAX_MEMO_VALUE))) {
29
- return { isValid: false };
30
- }
31
-
32
- return { isValid: true };
33
- }
@@ -1,15 +1,40 @@
1
1
  import { AccountBridge } from "@ledgerhq/types-live";
2
- import { broadcastTxn } from "./bridgeHelpers/icpRosetta";
2
+ import { broadcastTxn } from "../api";
3
3
  import { Transaction } from "../types";
4
+ import { log } from "@ledgerhq/logs";
5
+ import invariant from "invariant";
6
+ import { MAINNET_LEDGER_CANISTER_ID } from "../consts";
4
7
 
8
+ // Interface to structure raw data for broadcasting transactions
9
+ interface BroadcastRawData {
10
+ encodedSignedCallBlob: string;
11
+ }
12
+
13
+ // Type guard to validate rawData shape
14
+ function isBroadcastRawData(data: unknown): data is BroadcastRawData {
15
+ return (
16
+ typeof data === "object" &&
17
+ data !== null &&
18
+ "encodedSignedCallBlob" in data &&
19
+ typeof (data as any).encodedSignedCallBlob === "string"
20
+ );
21
+ }
22
+
23
+ // Main broadcast function for handling Internet Computer transactions
5
24
  export const broadcast: AccountBridge<Transaction>["broadcast"] = async ({
6
- signedOperation: { signature, operation },
25
+ signedOperation: { operation, rawData },
7
26
  }) => {
8
- // log("debug", "[broadcast] start fn");
27
+ log("debug", "[broadcast] Internet Computer transaction broadcast initiated");
9
28
 
10
- await broadcastTxn(signature);
29
+ // Validate rawData with type guard
30
+ invariant(isBroadcastRawData(rawData), "[ICP](broadcast) Invalid rawData format");
31
+ invariant(operation.extra, "[ICP](broadcast) Missing operation extra");
11
32
 
12
- const result = { ...operation };
33
+ await broadcastTxn(
34
+ Buffer.from(rawData.encodedSignedCallBlob, "hex"),
35
+ MAINNET_LEDGER_CANISTER_ID,
36
+ "call",
37
+ );
13
38
 
14
- return result;
39
+ return operation;
15
40
  };
@@ -7,7 +7,8 @@ import {
7
7
  } from "@ledgerhq/errors";
8
8
  import BigNumber from "bignumber.js";
9
9
  import { AccountBridge } from "@ledgerhq/types-live";
10
- import { getAddress, validateAddress, validateMemo } from "./bridgeHelpers/addresses";
10
+ import { getAddress } from "./bridgeHelpers/addresses";
11
+ import { validateAddress, validateMemo } from "@zondax/ledger-live-icp/utils";
11
12
  import { Transaction, TransactionStatus } from "../types";
12
13
  import { InvalidMemoICP } from "../errors";
13
14
 
@@ -1,6 +1,7 @@
1
1
  import { AccountBridge } from "@ledgerhq/types-live";
2
2
  import { Transaction } from "../types";
3
- import { getAddress, validateAddress } from "./bridgeHelpers/addresses";
3
+ import { getAddress } from "./bridgeHelpers/addresses";
4
+ import { validateAddress } from "@zondax/ledger-live-icp";
4
5
 
5
6
  export const prepareTransaction: AccountBridge<Transaction>["prepareTransaction"] = async (
6
7
  account,
@@ -1,53 +1,103 @@
1
1
  import { Observable } from "rxjs";
2
- import { Account, AccountBridge } from "@ledgerhq/types-live";
2
+ import { Account, AccountBridge, DeviceId } from "@ledgerhq/types-live";
3
3
  import { getAddress } from "./bridgeHelpers/addresses";
4
4
  import {
5
- getTxnExpirationDate,
6
- getTxnMetadata,
7
- getUnsignedTransaction,
8
- signICPTransaction,
9
- } from "./bridgeHelpers/icpRosetta";
5
+ UnsignedTransaction,
6
+ createUnsignedSendTransaction,
7
+ hashTransaction,
8
+ pubkeyToDer,
9
+ } from "@zondax/ledger-live-icp/utils";
10
+ import { Cbor } from "@zondax/ledger-live-icp/agent";
10
11
  import { buildOptimisticOperation } from "./buildOptimisticOperation";
11
12
  import { Transaction } from "../types";
12
13
  import { SignerContext } from "@ledgerhq/coin-framework/signer";
13
14
  import { ICPSigner } from "../types";
14
15
  import { getPath } from "../common-logic";
16
+ import { log } from "@ledgerhq/logs";
17
+ import invariant from "invariant";
18
+
19
+ const signICPTransaction = async (
20
+ unsignedTxn: UnsignedTransaction,
21
+ derivationPath: string,
22
+ signerContext: SignerContext<ICPSigner>,
23
+ account: Account,
24
+ deviceId: DeviceId,
25
+ ) => {
26
+ const blob = Cbor.encode({ content: unsignedTxn });
27
+ log("debug", "[signICPTransaction] blob", Buffer.from(blob).toString("hex"));
28
+ const signatures = await signerContext(deviceId, signer =>
29
+ signer.sign(derivationPath, Buffer.from(blob)),
30
+ );
31
+
32
+ invariant(signatures.signatureRS, "[ICP](signICPTransaction) Signature not found");
33
+ invariant(account.xpub, "[ICP](signICPTransaction) Account xpub is required");
34
+ return {
35
+ signature: Buffer.from(signatures.signatureRS).toString("hex"),
36
+ callBody: {
37
+ content: unsignedTxn,
38
+ sender_pubkey: pubkeyToDer(account.xpub),
39
+ sender_sig: signatures.signatureRS,
40
+ },
41
+ };
42
+ };
15
43
 
16
44
  export const buildSignOperation =
17
- (signerContext: SignerContext<ICPSigner>): AccountBridge<Transaction, Account>["signOperation"] =>
45
+ (signerContext: SignerContext<ICPSigner>): AccountBridge<Transaction>["signOperation"] =>
18
46
  ({ account, transaction, deviceId }) =>
19
47
  new Observable(o => {
20
48
  async function main() {
49
+ log("debug", "[signOperation] icp start fn");
50
+ log("debug", "[signOperation] transaction", transaction);
51
+
21
52
  const { xpub } = account;
53
+ invariant(xpub, "[ICP](signOperation) Account xpub is required");
54
+
22
55
  const { derivationPath } = getAddress(account);
23
- const { unsignedTxn, payloads } = await getUnsignedTransaction(transaction, account);
56
+
57
+ const { unsignedTransaction, transferRawRequest } = createUnsignedSendTransaction(
58
+ transaction,
59
+ xpub,
60
+ );
24
61
 
25
62
  o.next({
26
63
  type: "device-signature-requested",
27
64
  });
28
65
 
29
- const { signedTxn } = await signICPTransaction({
66
+ let signature: string = "";
67
+ let encodedSignedCallBlob: string = "";
68
+ const res = await signICPTransaction(
69
+ unsignedTransaction,
70
+ getPath(derivationPath),
30
71
  signerContext,
72
+ account,
31
73
  deviceId,
32
- unsignedTxn,
33
- path: getPath(derivationPath),
34
- payloads,
35
- pubkey: xpub ?? "",
36
- });
74
+ );
75
+ signature = res.signature;
76
+ encodedSignedCallBlob = Buffer.from(Cbor.encode(res.callBody)).toString("hex");
77
+ invariant(signature, "[ICP](signOperation) Signature not found");
37
78
 
38
79
  o.next({
39
80
  type: "device-signature-granted",
40
81
  });
41
82
 
42
- const { hash } = await getTxnMetadata(signedTxn);
43
- const operation = await buildOptimisticOperation(account, transaction, hash);
83
+ const hash = hashTransaction({
84
+ from: account.freshAddress,
85
+ to: transaction.recipient,
86
+ amount: transferRawRequest.amount.e8s,
87
+ fee: transferRawRequest.fee.e8s,
88
+ memo: transferRawRequest.memo,
89
+ created_at_time: transferRawRequest.created_at_time[0]["timestamp_nanos"],
90
+ });
44
91
 
92
+ const operation = await buildOptimisticOperation(account, transaction, hash);
45
93
  o.next({
46
94
  type: "signed",
47
95
  signedOperation: {
48
96
  operation,
49
- signature: signedTxn,
50
- expirationDate: getTxnExpirationDate(unsignedTxn),
97
+ signature,
98
+ rawData: {
99
+ encodedSignedCallBlob,
100
+ },
51
101
  },
52
102
  });
53
103
  }
package/src/consts.ts CHANGED
@@ -9,3 +9,13 @@ export const ICP_FEES = 1e4;
9
9
 
10
10
  // Max Memo value on ICP network
11
11
  export const MAX_MEMO_VALUE = Number.MAX_SAFE_INTEGER;
12
+
13
+ // API limits
14
+ export const FETCH_TXNS_LIMIT = 100;
15
+
16
+ export {
17
+ MAINNET_GOVERNANCE_CANISTER_ID,
18
+ MAINNET_LEDGER_CANISTER_ID,
19
+ MAINNET_INDEX_CANISTER_ID,
20
+ ICP_NETWORK_URL,
21
+ } from "@zondax/ledger-live-icp/neurons";
@@ -1,6 +1,5 @@
1
1
  import { log } from "@ledgerhq/logs";
2
2
  import { getBufferFromString } from "./common-logic/utils";
3
- import { ICP_SEND_TXN_TYPE } from "./consts";
4
3
  import { SignerContext } from "@ledgerhq/coin-framework/signer";
5
4
  import { ICPSigner } from "./types";
6
5
  import { Account, AnyMessage } from "@ledgerhq/types-live";
@@ -19,11 +18,7 @@ export const signMessage =
19
18
  if (typeof message !== "string") throw new Error("Message must be a string");
20
19
 
21
20
  const { r } = await signerContext(deviceId, async signer => {
22
- const r = await signer.sign(
23
- account.freshAddressPath,
24
- getBufferFromString(message),
25
- ICP_SEND_TXN_TYPE,
26
- );
21
+ const r = await signer.sign(account.freshAddressPath, getBufferFromString(message));
27
22
  return { r };
28
23
  });
29
24
 
@@ -18,5 +18,5 @@ export type ICPGetAddrResponse = {
18
18
  export interface ICPSigner {
19
19
  showAddressAndPubKey(path: string): Promise<ICPGetAddrResponse>;
20
20
  getAddressAndPubKey(path: string): Promise<ICPGetAddrResponse>;
21
- sign(path: string, message: Buffer, txtype: number): Promise<ICPSignature>;
21
+ sign(path: string, message: Buffer): Promise<ICPSignature>;
22
22
  }
@@ -1,30 +0,0 @@
1
- import { Account } from "@ledgerhq/types-live";
2
- import { Transaction } from "../../../types";
3
- import { ICPRosettaConstructionPayloadsResponse } from "./types";
4
- import { SignerContext } from "@ledgerhq/coin-framework/signer";
5
- import { ICPSigner } from "../../../types";
6
- export declare const getUnsignedTransaction: (transaction: Transaction, account: Account) => Promise<{
7
- unsignedTxn: string;
8
- payloads: ICPRosettaConstructionPayloadsResponse["payloads"];
9
- }>;
10
- export declare const signICPTransaction: ({ signerContext, deviceId, unsignedTxn, path, payloads, pubkey, }: {
11
- signerContext: SignerContext<ICPSigner>;
12
- deviceId: string;
13
- unsignedTxn: string;
14
- path: string;
15
- payloads: ICPRosettaConstructionPayloadsResponse["payloads"];
16
- pubkey: string;
17
- }) => Promise<{
18
- signatures: {
19
- txnSig: string;
20
- readSig: string;
21
- };
22
- signedTxn: string;
23
- }>;
24
- export declare const getTxnMetadata: (signedTxn: string) => Promise<{
25
- hash: string;
26
- }>;
27
- export declare const getTxnExpirationDate: (_unsignedTxn: string) => Date;
28
- export declare const broadcastTxn: (signedTxn: string) => Promise<void>;
29
- export declare const deriveAddressFromPubkey: (pubkey: string) => Promise<string>;
30
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/bridge/bridgeHelpers/icpRosetta/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE7C,OAAO,EAML,sCAAsC,EAKvC,MAAM,SAAS,CAAC;AAMjB,OAAO,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAChE,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE3C,eAAO,MAAM,sBAAsB,gBACpB,WAAW,WACf,OAAO;iBAEH,MAAM;cACT,sCAAsC,CAAC,UAAU,CAAC;EAwB7D,CAAC;AAEF,eAAO,MAAM,kBAAkB;mBAQd,cAAc,SAAS,CAAC;cAC7B,MAAM;iBACH,MAAM;UACb,MAAM;cACF,sCAAsC,CAAC,UAAU,CAAC;YACpD,MAAM;;gBAEF;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE;eACpC,MAAM;EA8ClB,CAAC;AAEF,eAAO,MAAM,cAAc,cAAqB,MAAM;UAAmB,MAAM;EAS9E,CAAC;AAEF,eAAO,MAAM,oBAAoB,iBAAkB,MAAM,KAAG,IAE3D,CAAC;AAEF,eAAO,MAAM,YAAY,cAAqB,MAAM,kBAKnD,CAAC;AAEF,eAAO,MAAM,uBAAuB,WAAkB,MAAM,oBAa3D,CAAC"}
@@ -1,88 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.deriveAddressFromPubkey = exports.broadcastTxn = exports.getTxnExpirationDate = exports.getTxnMetadata = exports.signICPTransaction = exports.getUnsignedTransaction = void 0;
7
- const api_1 = require("../../../api");
8
- const utils_1 = require("./utils");
9
- const agent_1 = require("@dfinity/agent");
10
- const principal_1 = require("@dfinity/principal");
11
- const bignumber_js_1 = __importDefault(require("bignumber.js"));
12
- const consts_1 = require("../../../consts");
13
- const getUnsignedTransaction = async (transaction, account) => {
14
- const ops = (0, utils_1.generateOperations)(transaction, account);
15
- const pubkeys = [
16
- {
17
- hex_bytes: account.xpub ?? "",
18
- curve_type: "secp256k1",
19
- },
20
- ];
21
- const reqOpts = {
22
- ...(0, api_1.getICPRosettaNetworkIdentifier)(),
23
- operations: ops,
24
- public_keys: pubkeys,
25
- metadata: {
26
- memo: parseInt(transaction.memo ?? "0"),
27
- },
28
- };
29
- const { payloads, unsigned_transaction } = await (0, api_1.constructionInvoke)(reqOpts, "payloads");
30
- return { unsignedTxn: unsigned_transaction, payloads };
31
- };
32
- exports.getUnsignedTransaction = getUnsignedTransaction;
33
- const signICPTransaction = async ({ signerContext, deviceId, unsignedTxn, path, payloads, pubkey, }) => {
34
- const decodedTxn = agent_1.Cbor.decode(Buffer.from(unsignedTxn, "hex"));
35
- const txnReqFromCbor = decodedTxn.updates[0][1];
36
- const expiry = new utils_1.ingressExpiry((0, bignumber_js_1.default)(decodedTxn.ingress_expiries[0].toString()));
37
- const submitReq = {
38
- request_type: "call",
39
- canister_id: principal_1.Principal.fromUint8Array(txnReqFromCbor.canister_id),
40
- method_name: txnReqFromCbor.method_name,
41
- arg: txnReqFromCbor.arg,
42
- sender: principal_1.Principal.fromUint8Array(txnReqFromCbor.sender),
43
- ingress_expiry: expiry,
44
- };
45
- const txnBlobToSign = agent_1.Cbor.encode({
46
- content: submitReq,
47
- });
48
- const { r } = await signerContext(deviceId, async (signer) => {
49
- const r = await signer.sign(path, Buffer.from(txnBlobToSign), consts_1.ICP_SEND_TXN_TYPE);
50
- return { r };
51
- });
52
- const result = {
53
- signatures: {
54
- readSig: "",
55
- txnSig: Buffer.from(r.signatureRS ?? "").toString("hex"),
56
- },
57
- };
58
- const signaturesPayload = (0, utils_1.generateSignaturesPayload)(result.signatures, payloads, pubkey);
59
- const { signed_transaction: signedTxn } = await (0, api_1.constructionInvoke)({
60
- ...(0, api_1.getICPRosettaNetworkIdentifier)(),
61
- signatures: signaturesPayload,
62
- unsigned_transaction: unsignedTxn,
63
- }, "combine");
64
- return { ...result, signedTxn };
65
- };
66
- exports.signICPTransaction = signICPTransaction;
67
- const getTxnMetadata = async (signedTxn) => {
68
- const { transaction_identifier: { hash }, } = await (0, api_1.constructionInvoke)({ ...(0, api_1.getICPRosettaNetworkIdentifier)(), signed_transaction: signedTxn }, "hash");
69
- return { hash };
70
- };
71
- exports.getTxnMetadata = getTxnMetadata;
72
- const getTxnExpirationDate = (_unsignedTxn) => {
73
- return new Date();
74
- };
75
- exports.getTxnExpirationDate = getTxnExpirationDate;
76
- const broadcastTxn = async (signedTxn) => {
77
- await (0, api_1.constructionInvoke)({ ...(0, api_1.getICPRosettaNetworkIdentifier)(), signed_transaction: signedTxn }, "submit");
78
- };
79
- exports.broadcastTxn = broadcastTxn;
80
- const deriveAddressFromPubkey = async (pubkey) => {
81
- const res = await (0, api_1.constructionInvoke)({
82
- ...(0, api_1.getICPRosettaNetworkIdentifier)(),
83
- public_key: { curve_type: "secp256k1", hex_bytes: pubkey },
84
- }, "derive");
85
- return res.account_identifier.address;
86
- };
87
- exports.deriveAddressFromPubkey = deriveAddressFromPubkey;
88
- //# sourceMappingURL=index.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/bridge/bridgeHelpers/icpRosetta/index.ts"],"names":[],"mappings":"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"}