@ledgerhq/coin-polkadot 0.0.2

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 (181) hide show
  1. package/.eslintrc.js +57 -0
  2. package/.turbo/turbo-build.log +4 -0
  3. package/CHANGELOG.md +12 -0
  4. package/jest.config.js +10 -0
  5. package/lib/account.d.ts +15 -0
  6. package/lib/account.d.ts.map +1 -0
  7. package/lib/account.js +133 -0
  8. package/lib/account.js.map +1 -0
  9. package/lib/address.d.ts +7 -0
  10. package/lib/address.d.ts.map +1 -0
  11. package/lib/address.js +28 -0
  12. package/lib/address.js.map +1 -0
  13. package/lib/api/bisontrails.d.ts +11 -0
  14. package/lib/api/bisontrails.d.ts.map +1 -0
  15. package/lib/api/bisontrails.js +351 -0
  16. package/lib/api/bisontrails.js.map +1 -0
  17. package/lib/api/common.d.ts +12 -0
  18. package/lib/api/common.d.ts.map +1 -0
  19. package/lib/api/common.js +41 -0
  20. package/lib/api/common.js.map +1 -0
  21. package/lib/api/index.d.ts +3 -0
  22. package/lib/api/index.d.ts.map +1 -0
  23. package/lib/api/index.js +53 -0
  24. package/lib/api/index.js.map +1 -0
  25. package/lib/api/sidecar.d.ts +193 -0
  26. package/lib/api/sidecar.d.ts.map +1 -0
  27. package/lib/api/sidecar.js +844 -0
  28. package/lib/api/sidecar.js.map +1 -0
  29. package/lib/api/sidecar.types.d.ts +163 -0
  30. package/lib/api/sidecar.types.d.ts.map +1 -0
  31. package/lib/api/sidecar.types.js +3 -0
  32. package/lib/api/sidecar.types.js.map +1 -0
  33. package/lib/api/subscan.d.ts +6 -0
  34. package/lib/api/subscan.d.ts.map +1 -0
  35. package/lib/api/subscan.js +375 -0
  36. package/lib/api/subscan.js.map +1 -0
  37. package/lib/api/websocket.d.ts +92 -0
  38. package/lib/api/websocket.d.ts.map +1 -0
  39. package/lib/api/websocket.js +759 -0
  40. package/lib/api/websocket.js.map +1 -0
  41. package/lib/bridge/js.d.ts +6 -0
  42. package/lib/bridge/js.d.ts.map +1 -0
  43. package/lib/bridge/js.js +120 -0
  44. package/lib/bridge/js.js.map +1 -0
  45. package/lib/bridge.integration.test.d.ts +4 -0
  46. package/lib/bridge.integration.test.d.ts.map +1 -0
  47. package/lib/bridge.integration.test.js +795 -0
  48. package/lib/bridge.integration.test.js.map +1 -0
  49. package/lib/cache.d.ts +65 -0
  50. package/lib/cache.d.ts.map +1 -0
  51. package/lib/cache.js +182 -0
  52. package/lib/cache.js.map +1 -0
  53. package/lib/cli-transaction.d.ts +44 -0
  54. package/lib/cli-transaction.d.ts.map +1 -0
  55. package/lib/cli-transaction.js +148 -0
  56. package/lib/cli-transaction.js.map +1 -0
  57. package/lib/deviceTransactionConfig.d.ts +16 -0
  58. package/lib/deviceTransactionConfig.d.ts.map +1 -0
  59. package/lib/deviceTransactionConfig.js +171 -0
  60. package/lib/deviceTransactionConfig.js.map +1 -0
  61. package/lib/errors.d.ts +37 -0
  62. package/lib/errors.d.ts.map +1 -0
  63. package/lib/errors.js +17 -0
  64. package/lib/errors.js.map +1 -0
  65. package/lib/hw-getAddress.d.ts +4 -0
  66. package/lib/hw-getAddress.d.ts.map +1 -0
  67. package/lib/hw-getAddress.js +64 -0
  68. package/lib/hw-getAddress.js.map +1 -0
  69. package/lib/js-buildTransaction.d.ts +25 -0
  70. package/lib/js-buildTransaction.d.ts.map +1 -0
  71. package/lib/js-buildTransaction.js +265 -0
  72. package/lib/js-buildTransaction.js.map +1 -0
  73. package/lib/js-createTransaction.d.ts +9 -0
  74. package/lib/js-createTransaction.d.ts.map +1 -0
  75. package/lib/js-createTransaction.js +22 -0
  76. package/lib/js-createTransaction.js.map +1 -0
  77. package/lib/js-estimateMaxSpendable.d.ts +15 -0
  78. package/lib/js-estimateMaxSpendable.d.ts.map +1 -0
  79. package/lib/js-estimateMaxSpendable.js +89 -0
  80. package/lib/js-estimateMaxSpendable.js.map +1 -0
  81. package/lib/js-getFeesForTransaction.d.ts +14 -0
  82. package/lib/js-getFeesForTransaction.d.ts.map +1 -0
  83. package/lib/js-getFeesForTransaction.js +94 -0
  84. package/lib/js-getFeesForTransaction.js.map +1 -0
  85. package/lib/js-getTransactionStatus.d.ts +18 -0
  86. package/lib/js-getTransactionStatus.d.ts.map +1 -0
  87. package/lib/js-getTransactionStatus.js +316 -0
  88. package/lib/js-getTransactionStatus.js.map +1 -0
  89. package/lib/js-prepareTransaction.d.ts +9 -0
  90. package/lib/js-prepareTransaction.d.ts.map +1 -0
  91. package/lib/js-prepareTransaction.js +83 -0
  92. package/lib/js-prepareTransaction.js.map +1 -0
  93. package/lib/js-signOperation.d.ts +27 -0
  94. package/lib/js-signOperation.d.ts.map +1 -0
  95. package/lib/js-signOperation.js +235 -0
  96. package/lib/js-signOperation.js.map +1 -0
  97. package/lib/js-synchronisation.d.ts +3 -0
  98. package/lib/js-synchronisation.d.ts.map +1 -0
  99. package/lib/js-synchronisation.js +104 -0
  100. package/lib/js-synchronisation.js.map +1 -0
  101. package/lib/logic.d.ts +107 -0
  102. package/lib/logic.d.ts.map +1 -0
  103. package/lib/logic.js +242 -0
  104. package/lib/logic.js.map +1 -0
  105. package/lib/platformAdapter.d.ts +11 -0
  106. package/lib/platformAdapter.d.ts.map +1 -0
  107. package/lib/platformAdapter.js +25 -0
  108. package/lib/platformAdapter.js.map +1 -0
  109. package/lib/platformAdapter.test.d.ts +2 -0
  110. package/lib/platformAdapter.test.d.ts.map +1 -0
  111. package/lib/platformAdapter.test.js +51 -0
  112. package/lib/platformAdapter.test.js.map +1 -0
  113. package/lib/polkadot-crypto.d.ts +2 -0
  114. package/lib/polkadot-crypto.d.ts.map +1 -0
  115. package/lib/polkadot-crypto.js +14 -0
  116. package/lib/polkadot-crypto.js.map +1 -0
  117. package/lib/preload.d.ts +14 -0
  118. package/lib/preload.d.ts.map +1 -0
  119. package/lib/preload.js +173 -0
  120. package/lib/preload.js.map +1 -0
  121. package/lib/serialization.d.ts +4 -0
  122. package/lib/serialization.d.ts.map +1 -0
  123. package/lib/serialization.js +51 -0
  124. package/lib/serialization.js.map +1 -0
  125. package/lib/specs.d.ts +7 -0
  126. package/lib/specs.d.ts.map +1 -0
  127. package/lib/specs.js +274 -0
  128. package/lib/specs.js.map +1 -0
  129. package/lib/speculos-deviceActions.d.ts +4 -0
  130. package/lib/speculos-deviceActions.d.ts.map +1 -0
  131. package/lib/speculos-deviceActions.js +85 -0
  132. package/lib/speculos-deviceActions.js.map +1 -0
  133. package/lib/transaction.d.ts +15 -0
  134. package/lib/transaction.d.ts.map +1 -0
  135. package/lib/transaction.js +51 -0
  136. package/lib/transaction.js.map +1 -0
  137. package/lib/types.d.ts +96 -0
  138. package/lib/types.d.ts.map +1 -0
  139. package/lib/types.js +3 -0
  140. package/lib/types.js.map +1 -0
  141. package/lib/validators.d.ts +3 -0
  142. package/lib/validators.d.ts.map +1 -0
  143. package/lib/validators.js +7 -0
  144. package/lib/validators.js.map +1 -0
  145. package/package.json +95 -0
  146. package/src/account.ts +170 -0
  147. package/src/address.ts +28 -0
  148. package/src/api/bisontrails.ts +343 -0
  149. package/src/api/common.ts +52 -0
  150. package/src/api/index.ts +38 -0
  151. package/src/api/sidecar.ts +735 -0
  152. package/src/api/sidecar.types.ts +162 -0
  153. package/src/api/subscan.ts +362 -0
  154. package/src/api/websocket.ts +535 -0
  155. package/src/bridge/js.ts +81 -0
  156. package/src/bridge.integration.test.ts +764 -0
  157. package/src/cache.ts +202 -0
  158. package/src/cli-transaction.ts +184 -0
  159. package/src/deviceTransactionConfig.ts +209 -0
  160. package/src/errors.ts +39 -0
  161. package/src/hw-getAddress.ts +14 -0
  162. package/src/js-buildTransaction.ts +206 -0
  163. package/src/js-createTransaction.ts +22 -0
  164. package/src/js-estimateMaxSpendable.ts +37 -0
  165. package/src/js-getFeesForTransaction.ts +41 -0
  166. package/src/js-getTransactionStatus.ts +350 -0
  167. package/src/js-prepareTransaction.ts +27 -0
  168. package/src/js-signOperation.ts +232 -0
  169. package/src/js-synchronisation.ts +57 -0
  170. package/src/logic.ts +266 -0
  171. package/src/platformAdapter.test.ts +61 -0
  172. package/src/platformAdapter.ts +29 -0
  173. package/src/polkadot-crypto.ts +10 -0
  174. package/src/preload.ts +148 -0
  175. package/src/serialization.ts +48 -0
  176. package/src/specs.ts +305 -0
  177. package/src/speculos-deviceActions.ts +84 -0
  178. package/src/transaction.ts +64 -0
  179. package/src/types.ts +118 -0
  180. package/src/validators.ts +2 -0
  181. package/tsconfig.json +21 -0
package/src/cache.ts ADDED
@@ -0,0 +1,202 @@
1
+ import { Extrinsics } from "@polkadot/types/metadata/decorate/types";
2
+ import { BigNumber } from "bignumber.js";
3
+ import { TypeRegistry } from "@polkadot/types";
4
+ import { makeLRUCache } from "@ledgerhq/coin-framework/cache";
5
+ import type { CacheRes } from "@ledgerhq/coin-framework/cache";
6
+ import type { PolkadotAccount, Transaction } from "./types";
7
+ import {
8
+ isNewAccount as apiIsNewAccount,
9
+ isControllerAddress as apiIsControllerAddress,
10
+ isElectionClosed as apiIsElectionClosed,
11
+ getRegistry as apiGetRegistry,
12
+ getTransactionParams as apiGetTransactionParams,
13
+ paymentInfo as apiPaymentInfo,
14
+ getMinimumBondBalance as apiGetMinimumBondBalance,
15
+ } from "./api";
16
+
17
+ /**
18
+ * Create a hash for a transaction that is params-specific and stay unchanged if no influcing fees
19
+ *
20
+ * @param {*} a
21
+ * @param {*} t
22
+ *
23
+ * @returns {string} hash
24
+ */
25
+ const hashTransactionParams = (
26
+ a: PolkadotAccount,
27
+ t: Transaction,
28
+ signedTx: string
29
+ ) => {
30
+ // Nonce is added to discard previous estimation when account is synced.
31
+ const prefix = `${a.id}_${a.polkadotResources?.nonce || 0}_${t.mode}`;
32
+ // Fees depends on extrinsic bytesize
33
+ const byteSize = signedTx.length;
34
+
35
+ // And on extrinsic weight (which varies with the method called)
36
+ switch (t.mode) {
37
+ case "send":
38
+ return `${prefix}_${byteSize}`;
39
+
40
+ case "bond":
41
+ return t.rewardDestination
42
+ ? `${prefix}_${byteSize}_${t.rewardDestination}`
43
+ : `${prefix}_${byteSize}`;
44
+
45
+ case "unbond":
46
+ case "rebond":
47
+ return `${prefix}_${byteSize}`;
48
+
49
+ case "nominate":
50
+ return `${prefix}_${t.validators?.length ?? "0"}`;
51
+
52
+ case "withdrawUnbonded":
53
+ return `${prefix}_${t.numSlashingSpans ?? "0"}`;
54
+
55
+ case "chill":
56
+ return `${prefix}`;
57
+ case "setController":
58
+ return `${prefix}`;
59
+ case "claimReward":
60
+ return `${prefix}_${t.era || "0"}`;
61
+
62
+ default:
63
+ throw new Error("Unknown mode in transaction");
64
+ }
65
+ };
66
+
67
+ /**
68
+ * Cache the getTransactionInfo for fees estimation to avoid multiple calls during 5 minutes.
69
+ * Should be force refresh when signing operation.
70
+ *
71
+ * @param {Account} account
72
+ *
73
+ * @returns {Promise<Object>} txInfo
74
+ */
75
+ export const getTransactionParams: CacheRes<
76
+ Array<void>,
77
+ Record<string, any>
78
+ > = makeLRUCache(
79
+ async (): Promise<Record<string, any>> => apiGetTransactionParams(),
80
+ () => "polkadot",
81
+ {
82
+ ttl: 5 * 60 * 1000, // 5 minutes
83
+ }
84
+ );
85
+
86
+ /**
87
+ * Cache the payment info (fee estimate), with a hash depending on fees-changing transaction params and tx size.
88
+ *
89
+ * @param {PolkadotAccount} arg1.a
90
+ * @param {Transaction} arg1.t
91
+ *
92
+ * @returns {Promise<BigBumber>}
93
+ */
94
+ export const getPaymentInfo: CacheRes<
95
+ Array<{
96
+ a: PolkadotAccount;
97
+ t: Transaction;
98
+ signedTx: string;
99
+ }>,
100
+ {
101
+ partialFee: string;
102
+ }
103
+ > = makeLRUCache(
104
+ async ({
105
+ signedTx,
106
+ }): Promise<{
107
+ partialFee: string;
108
+ }> => {
109
+ return await apiPaymentInfo(signedTx);
110
+ },
111
+ ({ a, t, signedTx }) => hashTransactionParams(a, t, signedTx),
112
+ {
113
+ ttl: 5 * 60 * 1000, // 5 minutes
114
+ }
115
+ );
116
+ export const getRegistry: CacheRes<
117
+ Array<void>,
118
+ { registry: TypeRegistry; extrinsics: Extrinsics }
119
+ > = makeLRUCache(
120
+ async (): Promise<{
121
+ registry: TypeRegistry;
122
+ extrinsics: Extrinsics;
123
+ }> => {
124
+ return await apiGetRegistry();
125
+ },
126
+ () => "polkadot",
127
+ {
128
+ ttl: 60 * 60 * 1000, // 1 hour - could be Infinity
129
+ }
130
+ );
131
+
132
+ /**
133
+ * Cache the isNewAccount to avoid multiple calls get checking tx status.
134
+ *
135
+ * @param {string} address
136
+ *
137
+ * @returns {Promise<boolean>}
138
+ */
139
+ export const isNewAccount: CacheRes<Array<string>, boolean> = makeLRUCache(
140
+ async (address): Promise<boolean> => {
141
+ return apiIsNewAccount(address);
142
+ },
143
+ (address) => address,
144
+ {
145
+ ttl: 60 * 1000, // 1 minute
146
+ }
147
+ );
148
+
149
+ /**
150
+ * Cache the isControllerAddress to avoid multiple calls get checking tx status.
151
+ *
152
+ * @param {string} address
153
+ *
154
+ * @returns {Promise<boolean>}
155
+ */
156
+ export const isControllerAddress: CacheRes<
157
+ Array<string>,
158
+ boolean
159
+ > = makeLRUCache(
160
+ async (address): Promise<boolean> => {
161
+ return apiIsControllerAddress(address);
162
+ },
163
+ (address) => address,
164
+ {
165
+ ttl: 5 * 60 * 1000, // 5 minutes
166
+ }
167
+ );
168
+
169
+ /**
170
+ * Cache the isElectionClosed to avoid multiple calls get checking tx status.
171
+ * Should be unused if currency is preloaded.
172
+ *
173
+ * @returns {Promise<boolean>}
174
+ */
175
+ export const isElectionClosed: CacheRes<Array<void>, boolean> = makeLRUCache(
176
+ async (): Promise<boolean> => {
177
+ return apiIsElectionClosed();
178
+ },
179
+ () => "",
180
+ {
181
+ ttl: 60 * 1000, // 1 minute
182
+ }
183
+ );
184
+
185
+ /**
186
+ * Cache the getMinimumBondBalance to avoid too many calls
187
+ *
188
+ * @async
189
+ *
190
+ * @returns {Promise<BigNumber>} consts
191
+ */
192
+ export const getMinimumBondBalance: CacheRes<
193
+ Array<void>,
194
+ BigNumber
195
+ > = makeLRUCache(
196
+ async (): Promise<BigNumber> => apiGetMinimumBondBalance(),
197
+ () => "polkadot",
198
+ {
199
+ max: 1, // Store only one object since we only have polkadot.
200
+ ttl: 60 * 60 * 1000, // 1 hour
201
+ }
202
+ );
@@ -0,0 +1,184 @@
1
+ import { from, Observable } from "rxjs";
2
+ import { map } from "rxjs/operators";
3
+ import { getValidators } from "./validators";
4
+ import invariant from "invariant";
5
+ import flatMap from "lodash/flatMap";
6
+ import { isAccount } from "@ledgerhq/coin-framework/account/index";
7
+ import {
8
+ getCryptoCurrencyById,
9
+ formatCurrencyUnit,
10
+ } from "@ledgerhq/coin-framework/currencies/index";
11
+ import {
12
+ SidecarValidatorsParamAddresses,
13
+ SidecarValidatorsParamStatus,
14
+ } from "./api/sidecar.types";
15
+ import { AccountLike } from "@ledgerhq/types-live";
16
+ import { PolkadotAccount, Transaction } from "./types";
17
+ const options = [
18
+ {
19
+ name: "mode",
20
+ type: String,
21
+ desc: "mode of transaction: send, nominate, bond, claimReward, withdrawUnbonded",
22
+ },
23
+ {
24
+ name: "fees",
25
+ type: String,
26
+ desc: "how much fees",
27
+ },
28
+ {
29
+ name: "validator",
30
+ type: String,
31
+ multiple: true,
32
+ desc: "address of recipient validator that will receive the delegate",
33
+ },
34
+ {
35
+ name: "era",
36
+ type: String,
37
+ desc: "Era of when to claim rewards",
38
+ },
39
+ /** Different possible destionation :
40
+ Staked - Pay into the stash account, increasing the amount at stake accordingly.
41
+ Stash - Pay into the stash account, not increasing the amount at stake.
42
+ Account - Pay into a custom account, like so: Account DMTHrNcmA8QbqRS4rBq8LXn8ipyczFoNMb1X4cY2WD9tdBX.
43
+ Controller - Pay into the controller account.
44
+ */
45
+ {
46
+ name: "rewardDestination",
47
+ type: String,
48
+ desc: "Reward destination",
49
+ },
50
+ ];
51
+ const polkadotValidatorsFormatters = {
52
+ json: (list) => JSON.stringify(list),
53
+ csv: (list) => {
54
+ const polkadotUnit = getCryptoCurrencyById("polkadot").units[0];
55
+ const csvHeader =
56
+ "ADDRESS IDENTITY TOTAL_BONDED SELF_BONDED NOMINATORS_COUNT COMMISSION REWARD_POINTS\n";
57
+ const csvList = list
58
+ .map(
59
+ (v) =>
60
+ `${v.address} "${v.identity}" ${formatCurrencyUnit(
61
+ polkadotUnit,
62
+ v.totalBonded,
63
+ {
64
+ showCode: false,
65
+ disableRounding: true,
66
+ useGrouping: false,
67
+ }
68
+ )} ${formatCurrencyUnit(polkadotUnit, v.selfBonded, {
69
+ showCode: false,
70
+ disableRounding: true,
71
+ useGrouping: false,
72
+ })} ${v.nominatorsCount} ${v.commission
73
+ .multipliedBy(100)
74
+ .toFixed(2)} ${v.rewardPoints}`
75
+ )
76
+ .join("\n");
77
+ return csvHeader + csvList;
78
+ },
79
+ default: (list) => {
80
+ const polkadotUnit = getCryptoCurrencyById("polkadot").units[0];
81
+ const tableList = list
82
+ .map(
83
+ (v) =>
84
+ `${v.address} "${v.identity}" ${formatCurrencyUnit(
85
+ polkadotUnit,
86
+ v.totalBonded,
87
+ {
88
+ showCode: true,
89
+ disableRounding: true,
90
+ useGrouping: false,
91
+ }
92
+ )} ${formatCurrencyUnit(polkadotUnit, v.selfBonded, {
93
+ showCode: true,
94
+ disableRounding: true,
95
+ useGrouping: false,
96
+ })} ${v.nominatorsCount} ${
97
+ v.commission.multipliedBy(100).toFixed(2) + "%"
98
+ } ${v.rewardPoints + " PTS"}`
99
+ )
100
+ .join("\n");
101
+ return tableList;
102
+ },
103
+ };
104
+ const polkadotValidators = {
105
+ args: [
106
+ {
107
+ name: "format",
108
+ desc: Object.keys(polkadotValidatorsFormatters).join("|"),
109
+ type: String,
110
+ },
111
+ {
112
+ name: "status",
113
+ desc: "The status of the validators to fetch (all|elected|waiting)",
114
+ type: String,
115
+ },
116
+ {
117
+ name: "validator",
118
+ type: String,
119
+ multiple: true,
120
+ desc: "address of recipient validator that will receive the delegate",
121
+ },
122
+ ],
123
+ job: ({
124
+ format,
125
+ status,
126
+ validator,
127
+ }: Partial<{
128
+ format: string;
129
+ status: SidecarValidatorsParamStatus | SidecarValidatorsParamAddresses;
130
+ validator: string[];
131
+ }>): Observable<string> =>
132
+ from(
133
+ getValidators(validator && validator.length ? validator : status)
134
+ ).pipe(
135
+ map((validators) => {
136
+ const f =
137
+ (format && polkadotValidatorsFormatters[format]) ||
138
+ polkadotValidatorsFormatters.default;
139
+ return f(validators);
140
+ })
141
+ ),
142
+ };
143
+
144
+ function inferTransactions(
145
+ transactions: Array<{
146
+ account: AccountLike;
147
+ transaction: Transaction;
148
+ }>,
149
+ opts: Record<string, any>,
150
+ { inferAmount }: any
151
+ ): Transaction[] {
152
+ return flatMap(transactions, ({ transaction, account }) => {
153
+ invariant(transaction.family === "polkadot", "polkadot family");
154
+
155
+ if (isAccount(account)) {
156
+ invariant(
157
+ (account as PolkadotAccount).polkadotResources,
158
+ "unactivated account"
159
+ );
160
+ }
161
+
162
+ const validators: string[] = opts["validator"] || [];
163
+ return {
164
+ ...transaction,
165
+ family: "polkadot",
166
+ fees: opts.fees ? inferAmount(account, opts.fees) : null,
167
+ mode: opts.mode || "send",
168
+ validators,
169
+ era: opts.era || null,
170
+ rewardDestination: opts.rewardDestination || null,
171
+ numSlashingSpans: isAccount(account)
172
+ ? (account as PolkadotAccount).polkadotResources?.numSlashingSpans
173
+ : null,
174
+ };
175
+ });
176
+ }
177
+
178
+ export default {
179
+ options,
180
+ inferTransactions,
181
+ commands: {
182
+ polkadotValidators,
183
+ },
184
+ };
@@ -0,0 +1,209 @@
1
+ import type { AccountLike, Account } from "@ledgerhq/types-live";
2
+ import type { PolkadotAccount, Transaction, TransactionStatus } from "./types";
3
+ import type { CommonDeviceTransactionField } from "@ledgerhq/coin-framework/transaction/common";
4
+ import { getMainAccount } from "@ledgerhq/coin-framework/account/index";
5
+ import {
6
+ formatCurrencyUnit,
7
+ getCryptoCurrencyById,
8
+ } from "@ledgerhq/coin-framework/currencies/index";
9
+ import { isStash } from "./logic";
10
+ const currency = getCryptoCurrencyById("polkadot");
11
+ export type ExtraDeviceTransactionField = {
12
+ type: "polkadot.validators";
13
+ label: string;
14
+ };
15
+ type DeviceTransactionField = CommonDeviceTransactionField &
16
+ ExtraDeviceTransactionField;
17
+
18
+ const getSendFields = ({
19
+ transaction,
20
+ status: { amount },
21
+ }: {
22
+ transaction: Transaction;
23
+ status: TransactionStatus;
24
+ }) => {
25
+ const fields: { type: string; label: string; value: string }[] = [];
26
+ fields.push({
27
+ type: "text",
28
+ label: "Balances",
29
+ value:
30
+ transaction && transaction.useAllAmount
31
+ ? "Transfer"
32
+ : "Transfer keep alive",
33
+ });
34
+ fields.push({
35
+ type: "text",
36
+ label: "Amount",
37
+ value: formatCurrencyUnit(currency.units[0], amount, {
38
+ showCode: true,
39
+ disableRounding: true,
40
+ }),
41
+ });
42
+ return fields;
43
+ };
44
+
45
+ function getDeviceTransactionConfig({
46
+ account,
47
+ parentAccount,
48
+ transaction,
49
+ status,
50
+ }: {
51
+ account: AccountLike;
52
+ parentAccount: Account | null | undefined;
53
+ transaction: Transaction;
54
+ status: TransactionStatus;
55
+ }): Array<DeviceTransactionField> {
56
+ const { mode, recipient, rewardDestination } = transaction;
57
+ const { amount } = status;
58
+ const mainAccount = getMainAccount(account, parentAccount) as PolkadotAccount;
59
+ let fields: { type: string; label: string; value?: string }[] = [];
60
+
61
+ switch (mode) {
62
+ case "send":
63
+ fields = getSendFields({
64
+ transaction,
65
+ status,
66
+ });
67
+ break;
68
+
69
+ case "nominate":
70
+ fields.push({
71
+ type: "text",
72
+ label: "Staking",
73
+ value: "Nominate",
74
+ });
75
+ fields.push({
76
+ type: "polkadot.validators",
77
+ label: "Targets",
78
+ });
79
+ break;
80
+
81
+ case "bond":
82
+ if (!isStash(mainAccount)) {
83
+ fields.push({
84
+ type: "text",
85
+ label: "Staking",
86
+ value: "Bond",
87
+ });
88
+ fields.push({
89
+ type: "text",
90
+ label: "Controller",
91
+ value: recipient,
92
+ });
93
+ fields.push({
94
+ type: "text",
95
+ label: "Amount",
96
+ value: formatCurrencyUnit(currency.units[0], amount, {
97
+ showCode: true,
98
+ disableRounding: true,
99
+ }),
100
+ });
101
+ fields.push({
102
+ type: "text",
103
+ label: "Payee",
104
+ value: rewardDestination || "Stash",
105
+ });
106
+ } else {
107
+ fields.push({
108
+ type: "text",
109
+ label: "Staking",
110
+ value: "Bond extra",
111
+ });
112
+ fields.push({
113
+ type: "text",
114
+ label: "Amount",
115
+ value: formatCurrencyUnit(currency.units[0], amount, {
116
+ showCode: true,
117
+ disableRounding: true,
118
+ }),
119
+ });
120
+ }
121
+
122
+ break;
123
+
124
+ case "rebond":
125
+ fields.push({
126
+ type: "text",
127
+ label: "Staking",
128
+ value: "Rebond",
129
+ });
130
+ fields.push({
131
+ type: "text",
132
+ label: "Amount",
133
+ value: formatCurrencyUnit(currency.units[0], amount, {
134
+ showCode: true,
135
+ disableRounding: true,
136
+ }),
137
+ });
138
+ break;
139
+
140
+ case "unbond":
141
+ fields.push({
142
+ type: "text",
143
+ label: "Staking",
144
+ value: "Unbond",
145
+ });
146
+ fields.push({
147
+ type: "text",
148
+ label: "Amount",
149
+ value: formatCurrencyUnit(currency.units[0], amount, {
150
+ showCode: true,
151
+ disableRounding: true,
152
+ }),
153
+ });
154
+ break;
155
+
156
+ case "chill":
157
+ fields.push({
158
+ type: "text",
159
+ label: "Staking",
160
+ value: "Chill",
161
+ });
162
+ break;
163
+
164
+ case "withdrawUnbonded":
165
+ fields.push({
166
+ type: "text",
167
+ label: "Staking",
168
+ value: "Withdraw Unbonded",
169
+ });
170
+ break;
171
+
172
+ case "setController":
173
+ fields.push({
174
+ type: "text",
175
+ label: "Staking",
176
+ value: "Set controller",
177
+ });
178
+ fields.push({
179
+ type: "text",
180
+ label: "Controller",
181
+ value:
182
+ // NOTE: I added this here as TokenAccount and ChildAccount
183
+ // both don't have freshAddress
184
+ account.type === "Account"
185
+ ? account.freshAddress
186
+ : mainAccount.freshAddress,
187
+ });
188
+ break;
189
+
190
+ case "claimReward":
191
+ fields.push({
192
+ type: "text",
193
+ label: "Staking",
194
+ value: "Payout Stakers",
195
+ });
196
+ break;
197
+
198
+ default:
199
+ break;
200
+ }
201
+
202
+ fields.push({
203
+ type: "fees",
204
+ label: "Fees",
205
+ });
206
+ return fields as DeviceTransactionField[];
207
+ }
208
+
209
+ export default getDeviceTransactionConfig;
package/src/errors.ts ADDED
@@ -0,0 +1,39 @@
1
+ import { createCustomErrorClass } from "@ledgerhq/errors";
2
+ export const PolkadotUnauthorizedOperation = createCustomErrorClass(
3
+ "PolkadotUnauthorizedOperation"
4
+ );
5
+ export const PolkadotElectionClosed = createCustomErrorClass(
6
+ "PolkadotElectionClosed"
7
+ );
8
+ export const PolkadotNotValidator = createCustomErrorClass(
9
+ "PolkadotNotValidator"
10
+ );
11
+ export const PolkadotLowBondedBalance = createCustomErrorClass(
12
+ "PolkadotLowBondedBalance"
13
+ );
14
+ export const PolkadotNoUnlockedBalance = createCustomErrorClass(
15
+ "PolkadotNoUnlockedBalance"
16
+ );
17
+ export const PolkadotNoNominations = createCustomErrorClass(
18
+ "PolkadotNoNominations"
19
+ );
20
+ export const PolkadotAllFundsWarning = createCustomErrorClass(
21
+ "PolkadotAllFundsWarning"
22
+ );
23
+ export const PolkadotBondMinimumAmount = createCustomErrorClass(
24
+ "PolkadotBondMinimumAmount"
25
+ );
26
+
27
+ export const PolkadotBondMinimumAmountWarning = createCustomErrorClass(
28
+ "PolkadotBondMinimumAmountWarning"
29
+ );
30
+
31
+ export const PolkadotMaxUnbonding = createCustomErrorClass(
32
+ "PolkadotMaxUnbonding"
33
+ );
34
+ export const PolkadotValidatorsRequired = createCustomErrorClass(
35
+ "PolkadotValidatorsRequired"
36
+ );
37
+ export const PolkadotDoMaxSendInstead = createCustomErrorClass(
38
+ "PolkadotDoMaxSendInstead"
39
+ );
@@ -0,0 +1,14 @@
1
+ import Polkadot from "@ledgerhq/hw-app-polkadot";
2
+ import type { Resolver } from "@ledgerhq/coin-framework/bridge/getAddressWrapper";
3
+
4
+ const resolver: Resolver = async (transport, { path, verify }) => {
5
+ const polkadot = new Polkadot(transport);
6
+ const r = await polkadot.getAddress(path, verify);
7
+ return {
8
+ address: r.address,
9
+ publicKey: r.pubKey,
10
+ path,
11
+ };
12
+ };
13
+
14
+ export default resolver;