@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
@@ -0,0 +1,162 @@
1
+ import type { HexString } from "@polkadot/util/types";
2
+
3
+ interface IAt {
4
+ hash: string;
5
+ height: string;
6
+ }
7
+ interface IBalanceLock {
8
+ id: string;
9
+ amount: string;
10
+ }
11
+ interface IPallet {
12
+ at: IAt;
13
+ pallet: string;
14
+ palletIndex: number;
15
+ }
16
+ interface IUnlocking {
17
+ value: string;
18
+ era: string;
19
+ }
20
+ interface IStakingLedger {
21
+ stash: string;
22
+ total: string;
23
+ active: string;
24
+ unlocking: IUnlocking[];
25
+ claimedRewards: string[];
26
+ }
27
+ interface ITarget {
28
+ address: string;
29
+ value: string;
30
+ status: "active" | "inactive" | "waiting" | null;
31
+ }
32
+ interface IIdentity {
33
+ display?: string;
34
+ displayParent?: string;
35
+ email?: string;
36
+ image?: string;
37
+ legal?: string;
38
+ other?: Record<string, any>;
39
+ parent?: string;
40
+ pgp?: string;
41
+ riot?: string;
42
+ twitter?: string;
43
+ web?: string;
44
+ judgements: Array<[string, Record<string, any>]>;
45
+ }
46
+ interface IValidatorExposure {
47
+ who: string;
48
+ value: string;
49
+ }
50
+ interface IValidator {
51
+ at?: IAt;
52
+ accountId: string;
53
+ controllerId?: string | null;
54
+ identity: IIdentity;
55
+ own: string;
56
+ total: string;
57
+ nominatorsCount: string;
58
+ nominators?: IValidatorExposure[];
59
+ commission: string;
60
+ rewardsPoints: string | null;
61
+ isElected: boolean;
62
+ isOversubscribed: boolean;
63
+ }
64
+ interface IChainType {
65
+ isDevelopment?: boolean;
66
+ isLocal?: boolean;
67
+ isLive?: boolean;
68
+ isCustom?: boolean;
69
+ asCustom?: Text;
70
+ }
71
+ interface IChainProperties {
72
+ ss58Format: string;
73
+ tokenDecimals: string;
74
+ tokenSymbol: string;
75
+ }
76
+ export interface SidecarAccountBalanceInfo {
77
+ at: IAt;
78
+ tokenSymbol: string;
79
+ nonce: string;
80
+ free: string;
81
+ reserved: string;
82
+ miscFrozen: string;
83
+ feeFrozen: string;
84
+ locks: IBalanceLock[];
85
+ }
86
+ export interface SidecarPallet {
87
+ at: IAt;
88
+ tokenSymbol: string;
89
+ nonce: string;
90
+ free: string;
91
+ reserved: string;
92
+ miscFrozen: string;
93
+ feeFrozen: string;
94
+ locks: IBalanceLock[];
95
+ }
96
+ export interface SidecarPalletStorageItem extends IPallet {
97
+ storageItem: string;
98
+ keys?: string[];
99
+ key1?: string;
100
+ key2?: string;
101
+ value?: any;
102
+ }
103
+ export interface SidecarStakingInfo {
104
+ at: IAt;
105
+ controller: string;
106
+ rewardDestination: string;
107
+ numSlashingSpans: string;
108
+ staking: IStakingLedger;
109
+ }
110
+ export interface SidecarNominations {
111
+ at?: IAt;
112
+ submittedIn: string | null;
113
+ targets: ITarget[];
114
+ }
115
+ export interface SidecarConstants {
116
+ at: IAt;
117
+ consts: Record<string, any>;
118
+ }
119
+ export type SidecarValidatorsParamStatus = "all" | "elected" | "waiting";
120
+ export type SidecarValidatorsParamAddresses = string[];
121
+ export type SidecarValidators = IValidator[];
122
+ export interface SidecarPalletStakingProgress {
123
+ at: IAt;
124
+ idealValidatorCount?: string | null;
125
+ activeEra: string | null;
126
+ forceEra: string;
127
+ nextActiveEraEstimate?: string;
128
+ nextSessionEstimate: string | null;
129
+ unappliedSlashes: string[] | null;
130
+ electionStatus?: {
131
+ status: Record<string, any>;
132
+ toggleEstimate: string | null;
133
+ };
134
+ validatorSet?: string[] | null;
135
+ }
136
+ export interface SidecarTransactionMaterial {
137
+ at: IAt;
138
+ genesisHash: string;
139
+ chainName: string;
140
+ specName: string;
141
+ specVersion: string;
142
+ txVersion: string;
143
+ metadata?: HexString;
144
+ }
145
+ export interface SidecarTransactionBroadcast {
146
+ hash: string;
147
+ }
148
+ export interface SidecarPaymentInfo {
149
+ weight: string;
150
+ class: string;
151
+ partialFee: string;
152
+ }
153
+ export interface SidecarRuntimeSpec {
154
+ at: IAt;
155
+ authoringVersion: string;
156
+ transactionVersion: string;
157
+ implVersion: string;
158
+ specName: string;
159
+ specVersion: string;
160
+ chainType: IChainType;
161
+ properties: IChainProperties;
162
+ }
@@ -0,0 +1,362 @@
1
+ /*
2
+
3
+ THIS FILE IS UNUSED AND PROVIDED AS EXAMPLE FOR USING SUBSCAN INDEXER.
4
+
5
+ */
6
+
7
+ /* eslint-disable */
8
+
9
+ /* istanbul ignore file */
10
+ import uniqBy from "lodash/uniqBy";
11
+ import camelCase from "lodash/camelCase";
12
+ import type { Operation } from "@ledgerhq/types-live";
13
+ import network from "@ledgerhq/coin-framework/network";
14
+ import { BigNumber } from "bignumber.js";
15
+ import { getEnv } from "@ledgerhq/coin-framework/env";
16
+ import { encodeAddress } from "@polkadot/util-crypto";
17
+ import { getOperationType } from "./common";
18
+ import type { PolkadotValidator } from "../types";
19
+
20
+ const getBaseApiUrl = () => getEnv("API_POLKADOT_INDEXER");
21
+
22
+ const DOT_REDOMINATION_BLOCK = 1248328;
23
+ const SUBSCAN_MULTIPLIER = 10000000000;
24
+ const SUBSCAN_ROW = 100;
25
+ const SUBSCAN_VALIDATOR_OVERSUBSCRIBED = 128;
26
+ const SUBSCAN_VALIDATOR_COMISSION_RATIO = 1000000000;
27
+
28
+ const encodePolkadotAddr = (addr) => {
29
+ return encodeAddress(
30
+ "0x" + addr,
31
+ /* SS58FORMAT= */
32
+ 0
33
+ );
34
+ };
35
+
36
+ const getExtra = (type, extrinsic) => {
37
+ let extra: {
38
+ transferAmount?: BigNumber;
39
+ palletMethod: string;
40
+ bondedAmount?: BigNumber;
41
+ unbondedAmount?: BigNumber;
42
+ amount?: BigNumber;
43
+ withdrawUnbondedAmount?: any;
44
+ validatorStash?: any;
45
+ validators?: any;
46
+ } = {
47
+ palletMethod: extrinsic.call_module
48
+ ? `${extrinsic.call_module}.${camelCase(extrinsic.call_module_function)}`
49
+ : `${extrinsic.module_id}.${camelCase(extrinsic.event_id)}`,
50
+ };
51
+ const params = JSON.parse(extrinsic.params);
52
+ let valueParam;
53
+
54
+ switch (type) {
55
+ case "OUT":
56
+ valueParam = params.find((p) => p.name === "value")?.value;
57
+ extra = { ...extra, transferAmount: new BigNumber(valueParam || 0) };
58
+ break;
59
+
60
+ case "BOND":
61
+ valueParam =
62
+ params.find((p) => p.name === "value")?.value ||
63
+ params.find((p) => p.name === "max_additional")?.value;
64
+ extra = { ...extra, bondedAmount: new BigNumber(valueParam || 0) };
65
+ break;
66
+
67
+ case "UNBOND":
68
+ extra = {
69
+ ...extra,
70
+ unbondedAmount: new BigNumber(
71
+ params.find((p) => p.name === "value")?.value || 0
72
+ ),
73
+ };
74
+ break;
75
+
76
+ case "SLASH":
77
+ case "REWARD_PAYOUT":
78
+ extra = {
79
+ ...extra,
80
+ validatorStash: encodePolkadotAddr(
81
+ params.find((p) => p.type === "AccountId").value
82
+ ),
83
+ amount: new BigNumber(params.find((p) => p.type === "Balance").value),
84
+ };
85
+ break;
86
+
87
+ case "NOMINATE":
88
+ extra = {
89
+ ...extra,
90
+ validators: params
91
+ .find((t) => t.name === "targets")
92
+ .value.reduce((old, current) => {
93
+ return current ? [...old, encodePolkadotAddr(current)] : old;
94
+ }, []),
95
+ };
96
+ break;
97
+ }
98
+
99
+ return extra;
100
+ };
101
+
102
+ const subscanAmountToPlanck = (amount, blockHeight) => {
103
+ if (blockHeight >= DOT_REDOMINATION_BLOCK) {
104
+ return new BigNumber(amount).multipliedBy(SUBSCAN_MULTIPLIER);
105
+ }
106
+
107
+ return new BigNumber(amount)
108
+ .multipliedBy(100)
109
+ .multipliedBy(SUBSCAN_MULTIPLIER);
110
+ };
111
+
112
+ const mapSubscanReward = ({ accountId }, reward): Partial<Operation> => {
113
+ const type = reward.event_id === "Reward" ? "REWARD_PAYOUT" : "SLASH";
114
+ const hash = reward.extrinsic_hash || reward.event_index; // Slashes are not extrinsics
115
+
116
+ return {
117
+ id: `${accountId}-${hash}-${type}`,
118
+ accountId,
119
+ fee: new BigNumber(0),
120
+ value: new BigNumber(reward.amount),
121
+ type,
122
+ hash: reward.extrinsic_hash,
123
+ blockHeight: reward.block_num,
124
+ date: new Date(reward.block_timestamp * 1000),
125
+ recipients: [],
126
+ senders: [],
127
+ extra: getExtra(type, reward),
128
+ };
129
+ };
130
+
131
+ const mapSubscanTransfer = (
132
+ { addr, accountId },
133
+ transfer
134
+ ): Partial<Operation> | null => {
135
+ const type = transfer.from === addr ? "OUT" : "IN";
136
+ const amount = subscanAmountToPlanck(transfer.amount, transfer.block_num);
137
+ return {
138
+ id: `${accountId}-${transfer.hash}-${type}`,
139
+ accountId,
140
+ fee: new BigNumber(transfer.fee),
141
+ value: !transfer.success ? new BigNumber(0) : amount,
142
+ type,
143
+ hash: transfer.hash,
144
+ blockHeight: transfer.block_num,
145
+ date: new Date(transfer.block_timestamp * 1000),
146
+ extra: {
147
+ palletMethod: "balances.transfer",
148
+ // FIXME subscan plz
149
+ transferAmount: amount,
150
+ },
151
+ senders: [transfer.from],
152
+ recipients: [transfer.to],
153
+ hasFailed: !transfer.success,
154
+ };
155
+ };
156
+
157
+ const mapSubscanExtrinsic = (
158
+ { addr, accountId },
159
+ extrinsic
160
+ ): Partial<Operation> => {
161
+ const pallet = extrinsic.call_module;
162
+ const palletMethod = camelCase(extrinsic.call_module_function);
163
+ const type = getOperationType(pallet, palletMethod);
164
+ // FIXME subscan WTF
165
+ const params = JSON.parse(extrinsic.params);
166
+ const paramRecipient = params.find((p) => p.name === "dest");
167
+ const paramAmount = params.find((p) => p.name === "value");
168
+ const recipient = paramRecipient && encodePolkadotAddr(paramRecipient.value);
169
+ // All successful transfers, but not self transfers (which only burn fees)
170
+ const value =
171
+ type === "OUT" && extrinsic.success && recipient !== addr && paramAmount
172
+ ? new BigNumber(paramAmount.value).plus(extrinsic.fee)
173
+ : new BigNumber(extrinsic.fee);
174
+ return {
175
+ id: `${accountId}-${extrinsic.extrinsic_hash}-${type}`,
176
+ accountId,
177
+ fee: new BigNumber(extrinsic.fee),
178
+ value,
179
+ type,
180
+ hash: extrinsic.extrinsic_hash,
181
+ blockHeight: extrinsic.block_num,
182
+ date: new Date(extrinsic.block_timestamp * 1000),
183
+ senders: [addr],
184
+ recipients: recipient ? [recipient] : [],
185
+ extra: getExtra(type, extrinsic),
186
+ hasFailed: !extrinsic.success,
187
+ transactionSequenceNumber:
188
+ extrinsic.signer === addr ? extrinsic.nonce : undefined,
189
+ };
190
+ };
191
+
192
+ const fetchSubscanList = async (
193
+ resourceName,
194
+ url,
195
+ mapFn,
196
+ mapArgs,
197
+ startAt,
198
+ page = 0,
199
+ prevOperations = []
200
+ ) => {
201
+ let operations;
202
+
203
+ if (prevOperations.length) {
204
+ const oldestBlockHeight = (
205
+ prevOperations[prevOperations.length - 1] as { blockHeight: number }
206
+ ).blockHeight;
207
+
208
+ if (oldestBlockHeight < startAt) {
209
+ return prevOperations.filter(
210
+ (o) => (o as { blockHeight: number }).blockHeight >= startAt
211
+ );
212
+ }
213
+ }
214
+
215
+ try {
216
+ const { data } = await network({
217
+ method: "POST",
218
+ url: `${getBaseApiUrl()}${url}`,
219
+ data: {
220
+ address: mapArgs.addr,
221
+ row: SUBSCAN_ROW,
222
+ page,
223
+ },
224
+ });
225
+
226
+ if (data.code !== 0) {
227
+ throw new Error(`SUBSCAN: ${data.message} - code ${data.code}`);
228
+ }
229
+
230
+ const list = data.data[resourceName] || [];
231
+ const count = data.data.count;
232
+ // console.log(`${url} - ${prevOperations.length} / ${count}`);
233
+ operations = [...prevOperations, ...list.map(mapFn.bind(null, mapArgs))];
234
+ return operations.length < count
235
+ ? fetchSubscanList(
236
+ resourceName,
237
+ url,
238
+ mapFn,
239
+ mapArgs,
240
+ startAt,
241
+ page + 1,
242
+ operations
243
+ )
244
+ : operations;
245
+ } catch (e) {
246
+ console.error(e);
247
+ throw e;
248
+ }
249
+ };
250
+
251
+ export const getOperations = async (
252
+ accountId: string,
253
+ addr: string,
254
+ startAt: number = 0
255
+ ) => {
256
+ const mapArgs = {
257
+ addr,
258
+ accountId,
259
+ };
260
+ const [extrinsicsOp, transfersOp, rewardsOp] = await Promise.all([
261
+ fetchSubscanList(
262
+ "extrinsics",
263
+ "/api/scan/extrinsics",
264
+ mapSubscanExtrinsic,
265
+ mapArgs,
266
+ startAt
267
+ ),
268
+ fetchSubscanList(
269
+ "transfers",
270
+ "/api/scan/transfers",
271
+ mapSubscanTransfer,
272
+ mapArgs,
273
+ startAt
274
+ ),
275
+ fetchSubscanList(
276
+ "list",
277
+ "/api/scan/account/reward_slash",
278
+ mapSubscanReward,
279
+ mapArgs,
280
+ startAt
281
+ ),
282
+ ]);
283
+ const incomingTransfers = transfersOp.filter((t) => t.type === "IN");
284
+ const operations = uniqBy<Operation>(
285
+ [...extrinsicsOp, ...incomingTransfers, ...rewardsOp],
286
+ (op) => op.id
287
+ );
288
+ operations.sort((a, b) => (b.date as any) - (a.date as any));
289
+ return operations;
290
+ };
291
+
292
+ const mapSubscanValidator = (validator, isElected): PolkadotValidator => {
293
+ return {
294
+ address: validator.stash_account_display.address,
295
+ identity: validator.stash_account_display.display,
296
+ nominatorsCount: validator.count_nominators,
297
+ rewardPoints: validator.reward_point,
298
+ commission: new BigNumber(validator.validator_prefs_value).dividedBy(
299
+ SUBSCAN_VALIDATOR_COMISSION_RATIO
300
+ ),
301
+ totalBonded: new BigNumber(validator.bonded_nominators).plus(
302
+ validator.bonded_owner
303
+ ),
304
+ selfBonded: new BigNumber(validator.bonded_owner),
305
+ isElected,
306
+ isOversubscribed:
307
+ validator.count_nominators >= SUBSCAN_VALIDATOR_OVERSUBSCRIBED,
308
+ };
309
+ };
310
+
311
+ const fetchSubscanValidators = async (isElected) => {
312
+ // Cannot fetch both at the same time through subscan
313
+ const url = isElected
314
+ ? "/api/scan/staking/validators"
315
+ : "/api/scan/staking/waiting";
316
+
317
+ try {
318
+ const { data } = await network({
319
+ method: "POST",
320
+ url: `${getBaseApiUrl()}${url}`,
321
+ data: {},
322
+ });
323
+
324
+ if (data.code !== 0) {
325
+ throw new Error(`SUBSCAN: ${data.message} - code ${data.code}`);
326
+ }
327
+
328
+ const validators = data.data.list.map((v) =>
329
+ mapSubscanValidator(v, isElected)
330
+ );
331
+ return validators;
332
+ } catch (e) {
333
+ console.error(e);
334
+ throw e;
335
+ }
336
+ };
337
+
338
+ /**
339
+ * List all validators for the current era, and their exposure.
340
+ */
341
+ export const getValidators = async (stashes: string | string[] = "elected") => {
342
+ if (stashes === "elected") {
343
+ return fetchSubscanValidators(true);
344
+ } else if (stashes === "waiting") {
345
+ return fetchSubscanValidators(false);
346
+ } else if (stashes === "all" || Array.isArray(stashes)) {
347
+ const [elected, waiting] = await Promise.all([
348
+ fetchSubscanValidators(true),
349
+ fetchSubscanValidators(false),
350
+ ]);
351
+
352
+ if (Array.isArray(stashes)) {
353
+ return [...elected, ...waiting].filter((v) =>
354
+ stashes.includes(v.address)
355
+ );
356
+ }
357
+
358
+ return [...elected, ...waiting];
359
+ }
360
+
361
+ return [];
362
+ };