@airgap/icp 0.13.15-beta.4 → 0.13.15-beta.6

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.
@@ -1,4 +1,27 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
2
25
  var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
26
  function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
27
  return new (P || (P = Promise))(function (resolve, reject) {
@@ -17,11 +40,15 @@ const coinlib_core_1 = require("@airgap/coinlib-core");
17
40
  const index_1 = __importDefault(require("@airgap/coinlib-core/dependencies/src/axios-0.19.0/index"));
18
41
  const bignumber_1 = __importDefault(require("@airgap/coinlib-core/dependencies/src/bignumber.js-9.0.0/bignumber"));
19
42
  const errors_1 = require("@airgap/coinlib-core/errors");
43
+ const assert_1 = require("@airgap/coinlib-core/utils/assert");
20
44
  const array_1 = require("@airgap/coinlib-core/utils/array");
21
45
  const crypto_1 = require("@airgap/crypto");
22
46
  const module_kit_1 = require("@airgap/module-kit");
47
+ const governance_1 = require("../types/governance");
23
48
  const transaction_1 = require("../types/transaction");
24
49
  const account_1 = require("../utils/account");
50
+ const Cbor = __importStar(require("../utils/cbor"));
51
+ const IDL = __importStar(require("../utils/idl"));
25
52
  const principal_1 = require("../utils/principal");
26
53
  const ICPGovernance_1 = require("./ICPGovernance");
27
54
  const ICPImplementation_1 = require("./ICPImplementation");
@@ -73,6 +100,10 @@ class ICPProtocolImpl {
73
100
  algorithm: 'secp256k1'
74
101
  };
75
102
  this.options = createICPProtocolOptions(options.network);
103
+ this.canisterId = {
104
+ ledger: this.options.network.ledgerCanisterId,
105
+ governance: this.options.network.governanceCanisterId
106
+ };
76
107
  }
77
108
  getMetadata() {
78
109
  return __awaiter(this, void 0, void 0, function* () {
@@ -103,21 +134,19 @@ class ICPProtocolImpl {
103
134
  case transaction_1.ICPActionType.TRANSFER:
104
135
  return (0, ICPImplementation_1.getDetailsFromSignedTransactionTransfer)(encoded, publicKey.value, this.options.network);
105
136
  case transaction_1.ICPActionType.GET_NEURON_INFO:
106
- return (0, ICPGovernance_1.getDetailsFromSignedTransactionGetNeuronInfo)(publicKey.value, this.options.network);
137
+ return (0, ICPGovernance_1.getDetailsFromSignedGetNeuronInfo)(publicKey.value, this.options.network);
107
138
  case transaction_1.ICPActionType.TRANSFER_TO_SUBACCOUNT:
108
- return (0, ICPGovernance_1.getDetailsFromSignedTransactionTransferToSubaccount)(encoded, publicKey.value, this.options.network);
139
+ return (0, ICPGovernance_1.getDetailsFromSignedTransferToSubaccount)(encoded, publicKey.value, this.options.network);
109
140
  case transaction_1.ICPActionType.CLAIM_GOVERNANCE:
110
- return (0, ICPGovernance_1.getDetailsFromSignedTransactionClaimGovernance)(publicKey.value, this.options.network);
141
+ return (0, ICPGovernance_1.getDetailsFromTransactionClaimGovernance)(publicKey.value, this.options.network);
111
142
  case transaction_1.ICPActionType.FOLLOW_NEURON:
112
- return (0, ICPGovernance_1.getDetailsFromSignedTransactionFollowNeuron)(publicKey.value, this.options.network);
113
- case transaction_1.ICPActionType.INCREASE_STAKE:
114
- throw new Error('TODO: implement');
115
- case transaction_1.ICPActionType.REMOVE_STAKE:
116
- return (0, ICPGovernance_1.getDetailsFromSignedTransactionRemoveStake)(publicKey.value, this.options.network);
117
- case transaction_1.ICPActionType.INCREASE_DELAY:
143
+ return (0, ICPGovernance_1.getDetailsFromSignedFollowNeuron)(publicKey.value, this.options.network);
144
+ case transaction_1.ICPActionType.DISBURSE:
145
+ return (0, ICPGovernance_1.getDetailsFromSignedDisburse)(publicKey.value, this.options.network);
146
+ case transaction_1.ICPActionType.INCREASE_DISSOLVING_DELAY:
118
147
  return (0, ICPGovernance_1.getDetailsFromSignedTransactionIncreaseDelay)(publicKey.value, this.options.network);
119
148
  case transaction_1.ICPActionType.START_DISSOLVING:
120
- return (0, ICPGovernance_1.getDetailsFromSignedTransactionStartDissolving)(publicKey.value, this.options.network);
149
+ return (0, ICPGovernance_1.getDetailsFromSignedStartDissolving)(publicKey.value, this.options.network);
121
150
  case transaction_1.ICPActionType.STOP_DISSOLVING:
122
151
  return (0, ICPGovernance_1.getDetailsFromSignedTransactionStopDissolving)(publicKey.value, this.options.network);
123
152
  case transaction_1.ICPActionType.RESTAKE_MATURITY:
@@ -135,23 +164,21 @@ class ICPProtocolImpl {
135
164
  case transaction_1.ICPActionType.TRANSFER:
136
165
  return (0, ICPImplementation_1.getDetailsFromUnsignedTransactionTransfer)(encoded, publicKey.value, this.options.network);
137
166
  case transaction_1.ICPActionType.GET_NEURON_INFO:
138
- return (0, ICPGovernance_1.getDetailsFromUnsignedTransactionGetNeuronInfo)(publicKey.value, this.options.network);
167
+ return (0, ICPGovernance_1.getDetailsFromUnsignedGetNeuronInfo)(publicKey.value, this.options.network);
139
168
  case transaction_1.ICPActionType.TRANSFER_TO_SUBACCOUNT:
140
- return (0, ICPGovernance_1.getDetailsFromUnsignedTransactionTransferToSubaccount)(encoded, publicKey.value, this.options.network);
169
+ return (0, ICPGovernance_1.getDetailsFromUnsignedTransferToSubaccount)(encoded, publicKey.value, this.options.network);
141
170
  case transaction_1.ICPActionType.CLAIM_GOVERNANCE:
142
- return (0, ICPGovernance_1.getDetailsFromUnsignedTransactionClaimGovernance)(publicKey.value, this.options.network);
143
- case transaction_1.ICPActionType.INCREASE_STAKE:
144
- throw new Error('TODO: implement');
145
- case transaction_1.ICPActionType.REMOVE_STAKE:
146
- return (0, ICPGovernance_1.getDetailsFromUnsignedTransactionRemoveStake)(publicKey.value, this.options.network);
147
- case transaction_1.ICPActionType.INCREASE_DELAY:
171
+ return (0, ICPGovernance_1.getDetailsFromUnsignedClaimGovernance)(publicKey.value, this.options.network);
172
+ case transaction_1.ICPActionType.DISBURSE:
173
+ return (0, ICPGovernance_1.getDetailsFromUnsignedDisburse)(publicKey.value, this.options.network);
174
+ case transaction_1.ICPActionType.INCREASE_DISSOLVING_DELAY:
148
175
  return (0, ICPGovernance_1.getDetailsFromUnsignedTransactionIncreaseDelay)(publicKey.value, this.options.network);
149
176
  case transaction_1.ICPActionType.START_DISSOLVING:
150
- return (0, ICPGovernance_1.getDetailsFromUnsignedTransactionStartDissolving)(publicKey.value, this.options.network);
177
+ return (0, ICPGovernance_1.getDetailsFromUnsignedStartDissolving)(publicKey.value, this.options.network);
151
178
  case transaction_1.ICPActionType.STOP_DISSOLVING:
152
179
  return (0, ICPGovernance_1.getDetailsFromUnsignedTransactionStopDissolving)(publicKey.value, this.options.network);
153
180
  case transaction_1.ICPActionType.FOLLOW_NEURON:
154
- return (0, ICPGovernance_1.getDetailsFromUnsignedTransactionFollowNeuron)(publicKey.value, this.options.network);
181
+ return (0, ICPGovernance_1.getDetailsFromUnsignedFollowNeuron)(publicKey.value, this.options.network);
155
182
  case transaction_1.ICPActionType.RESTAKE_MATURITY:
156
183
  return (0, ICPGovernance_1.getDetailsFromUnsignedTransactionRestakeMaturity)(publicKey.value, this.options.network);
157
184
  default:
@@ -186,64 +213,52 @@ class ICPProtocolImpl {
186
213
  case transaction_1.ICPActionType.TRANSFER:
187
214
  return {
188
215
  actionType,
189
- encoded: yield (0, ICPImplementation_1.signTransactionTransfer)(encoded, secretKey.value, this.options.network.ledgerCanisterId),
190
- requestType: 'update'
216
+ encoded: yield (0, ICPImplementation_1.signTransactionTransfer)(encoded, secretKey.value, this.options.network.ledgerCanisterId)
191
217
  };
192
218
  case transaction_1.ICPActionType.GET_NEURON_INFO:
193
219
  return {
194
220
  actionType,
195
- encoded: yield (0, ICPGovernance_1.signTransactionGetNeuronInfo)(encoded, secretKey.value, this.options.network.governanceCanisterId),
196
- requestType: 'query'
221
+ encoded: yield (0, ICPGovernance_1.signGetNeuronInfo)(encoded, secretKey.value, this.options.network.governanceCanisterId)
197
222
  };
198
223
  case transaction_1.ICPActionType.TRANSFER_TO_SUBACCOUNT:
199
224
  return {
200
225
  actionType,
201
- encoded: yield (0, ICPGovernance_1.signTransactionTransferToSubaccount)(encoded, secretKey.value, this.options.network.ledgerCanisterId),
202
- requestType: 'update'
226
+ encoded: yield (0, ICPGovernance_1.signTransferToSubaccount)(encoded, secretKey.value, this.options.network.ledgerCanisterId)
203
227
  };
204
228
  case transaction_1.ICPActionType.CLAIM_GOVERNANCE:
205
229
  return {
206
230
  actionType,
207
- encoded: yield (0, ICPGovernance_1.signTransactionClaimGovernance)(encoded, secretKey.value, this.options.network.ledgerCanisterId),
208
- requestType: 'update'
231
+ encoded: yield (0, ICPGovernance_1.signClaimGovernance)(encoded, secretKey.value, this.options.network.governanceCanisterId)
209
232
  };
210
- case transaction_1.ICPActionType.INCREASE_STAKE:
211
- throw new Error('TODO: implement');
212
- case transaction_1.ICPActionType.REMOVE_STAKE:
233
+ case transaction_1.ICPActionType.DISBURSE:
213
234
  return {
214
235
  actionType,
215
- encoded: yield (0, ICPGovernance_1.signTransactionRemoveStake)(encoded, secretKey.value, this.options.network.ledgerCanisterId),
216
- requestType: 'update'
236
+ encoded: yield (0, ICPGovernance_1.signDisburse)(encoded, secretKey.value, this.options.network.governanceCanisterId)
217
237
  };
218
- case transaction_1.ICPActionType.INCREASE_DELAY:
238
+ case transaction_1.ICPActionType.INCREASE_DISSOLVING_DELAY:
219
239
  return {
220
240
  actionType,
221
- encoded: yield (0, ICPGovernance_1.signTransactionIncreaseDelay)(encoded, secretKey.value, this.options.network.ledgerCanisterId),
222
- requestType: 'update'
241
+ encoded: yield (0, ICPGovernance_1.signTransactionIncreaseDelay)(encoded, secretKey.value, this.options.network.governanceCanisterId)
223
242
  };
224
243
  case transaction_1.ICPActionType.START_DISSOLVING:
225
244
  return {
226
245
  actionType,
227
- encoded: yield (0, ICPGovernance_1.signTransactionStartDissolving)(encoded, secretKey.value, this.options.network.ledgerCanisterId),
228
- requestType: 'update'
246
+ encoded: yield (0, ICPGovernance_1.signStartDissolving)(encoded, secretKey.value, this.options.network.governanceCanisterId)
229
247
  };
230
248
  case transaction_1.ICPActionType.STOP_DISSOLVING:
231
249
  return {
232
250
  actionType,
233
- encoded: yield (0, ICPGovernance_1.signTransactionStopDissolving)(encoded, secretKey.value, this.options.network.ledgerCanisterId),
234
- requestType: 'update'
251
+ encoded: yield (0, ICPGovernance_1.signTransactionStopDissolving)(encoded, secretKey.value, this.options.network.governanceCanisterId)
235
252
  };
236
253
  case transaction_1.ICPActionType.FOLLOW_NEURON:
237
254
  return {
238
255
  actionType,
239
- encoded: yield (0, ICPGovernance_1.signTransactionFollowNeuron)(encoded, secretKey.value, this.options.network.ledgerCanisterId),
240
- requestType: 'update'
256
+ encoded: yield (0, ICPGovernance_1.signFollowNeuron)(encoded, secretKey.value, this.options.network.governanceCanisterId)
241
257
  };
242
258
  case transaction_1.ICPActionType.RESTAKE_MATURITY:
243
259
  return {
244
260
  actionType,
245
- encoded: yield (0, ICPGovernance_1.signTransactionRestakeMaturity)(encoded, secretKey.value, this.options.network.ledgerCanisterId),
246
- requestType: 'update'
261
+ encoded: yield (0, ICPGovernance_1.signTransactionRestakeMaturity)(encoded, secretKey.value, this.options.network.governanceCanisterId)
247
262
  };
248
263
  default:
249
264
  (0, coinlib_core_1.assertNever)(actionType);
@@ -304,7 +319,16 @@ class ICPProtocolImpl {
304
319
  getBalanceOfPublicKey(publicKey) {
305
320
  return __awaiter(this, void 0, void 0, function* () {
306
321
  const address = (0, ICPImplementation_1.getAddressFromPublicKey)(publicKey.value);
307
- return this.getBalanceOfAddress(address);
322
+ const mainBalance = yield this.getBalanceOfAddress(address);
323
+ const neuronBalance = yield this.getNeuronBalance(publicKey);
324
+ const totalBalance = (0, module_kit_1.newAmount)(mainBalance.total)
325
+ .blockchain(this.units)
326
+ .toBigNumber()
327
+ .plus((0, module_kit_1.newAmount)(neuronBalance.total).blockchain(this.units).toBigNumber());
328
+ return {
329
+ total: (0, module_kit_1.newAmount)(totalBalance, 'blockchain'),
330
+ transferable: mainBalance.total
331
+ };
308
332
  });
309
333
  }
310
334
  getBalanceOfAddress(address) {
@@ -325,7 +349,7 @@ class ICPProtocolImpl {
325
349
  }
326
350
  else {
327
351
  const feeEstimation = yield this.getTransactionFeeWithPublicKey(publicKey, []);
328
- fee = new bignumber_1.default((0, module_kit_1.newAmount)(feeEstimation.medium).value);
352
+ fee = new bignumber_1.default((0, module_kit_1.newAmount)(feeEstimation).value);
329
353
  if (fee.gte(balanceBn)) {
330
354
  fee = new bignumber_1.default(0);
331
355
  }
@@ -347,7 +371,7 @@ class ICPProtocolImpl {
347
371
  // medium: newAmount(feeDefault.toString(10), 'ICP'),
348
372
  // high: newAmount(feeDefault.toString(10), 'ICP')
349
373
  // }
350
- return this.feeDefaults;
374
+ return this.feeDefaults.medium;
351
375
  });
352
376
  }
353
377
  prepareTransactionWithPublicKey(publicKey, details, configuration) {
@@ -363,15 +387,12 @@ class ICPProtocolImpl {
363
387
  throw new errors_1.BalanceError(coinlib_core_1.Domain.ICP, 'not enough balance');
364
388
  }
365
389
  const amountBn = BigInt((0, module_kit_1.newAmount)(details[0].amount).blockchain(this.units).value);
366
- // Transaction object
367
- const transaction = {
368
- from: (0, ICPImplementation_1.getAddressFromPublicKey)(publicKey.value),
390
+ // Create unsigned
391
+ const unsignedTransaction = (0, ICPImplementation_1.createUnsignedTransaction)({
369
392
  to: details[0].to,
370
393
  amount: amountBn,
371
394
  fee: feeBn
372
- };
373
- // Create unsigned
374
- const unsignedTransaction = (0, ICPImplementation_1.createUnsignedTransaction)(transaction);
395
+ });
375
396
  return (0, module_kit_1.newUnsignedTransaction)({
376
397
  transactions: [
377
398
  {
@@ -387,10 +408,87 @@ class ICPProtocolImpl {
387
408
  // Search for : Transfer ICP from the caller to the destination accountIdentifier. Returns the index of the block containing the tx if it was successful.
388
409
  broadcastTransaction(transaction) {
389
410
  return __awaiter(this, void 0, void 0, function* () {
390
- const txHashes = yield Promise.all(transaction.transactions.map(({ actionType, encoded }) => (0, ICPImplementation_1.broadcastTransaction)(encoded, this.options.network.rpcUrl, this.options.network.governanceCanisterId, transaction_1.ICP_REQUEST_TYPE_PER_ACTION[actionType])));
391
- return txHashes[0];
411
+ for (const { actionType, encoded } of transaction.transactions) {
412
+ const requestType = transaction_1.ICP_REQUEST_TYPE_PER_ACTION[actionType];
413
+ if (requestType !== 'call')
414
+ continue;
415
+ yield (0, ICPImplementation_1.broadcastTransaction)(encoded, this.options.network.rpcUrl, this.canisterId[transaction_1.ICP_CANISTER_TYPE_PER_ACTION[actionType]], transaction_1.ICP_REQUEST_TYPE_PER_ACTION[actionType]);
416
+ }
417
+ return '';
392
418
  });
393
419
  }
420
+ sendQuery(transaction) {
421
+ return __awaiter(this, void 0, void 0, function* () {
422
+ return Promise.all(transaction.transactions
423
+ .filter(({ actionType }) => transaction_1.ICP_REQUEST_TYPE_PER_ACTION[actionType] === 'query')
424
+ .map(({ actionType, encoded }) => __awaiter(this, void 0, void 0, function* () {
425
+ const response = yield (0, ICPImplementation_1.broadcastTransaction)(encoded, this.options.network.rpcUrl, this.canisterId[transaction_1.ICP_CANISTER_TYPE_PER_ACTION[actionType]], transaction_1.ICP_REQUEST_TYPE_PER_ACTION[actionType]);
426
+ const queryResponse = Cbor.decode(response);
427
+ if (queryResponse.status == "rejected" /* QueryResponseStatus.Rejected */) {
428
+ throw new errors_1.NetworkError(coinlib_core_1.Domain.ICP, {}, `Error (${queryResponse.reject_code}) ${queryResponse.reject_message}`);
429
+ }
430
+ return this.decodeQueryResponse(actionType, queryResponse.reply.arg);
431
+ })));
432
+ });
433
+ }
434
+ decodeQueryResponse(actionType, response) {
435
+ switch (actionType) {
436
+ case transaction_1.ICPActionType.GET_NEURON_INFO:
437
+ const NeuronId = IDL.Record({ id: IDL.Nat64 });
438
+ const BallotInfo = IDL.Record({
439
+ vote: IDL.Int32,
440
+ proposal_id: IDL.Opt(NeuronId)
441
+ });
442
+ const DissolveState = IDL.Variant({
443
+ DissolveDelaySeconds: IDL.Nat64,
444
+ WhenDissolvedTimestampSeconds: IDL.Nat64
445
+ });
446
+ const Followees = IDL.Record({ followees: IDL.Vec(NeuronId) });
447
+ const NeuronStakeTransfer = IDL.Record({
448
+ to_subaccount: IDL.Vec(IDL.Nat8),
449
+ neuron_stake_e8s: IDL.Nat64,
450
+ from: IDL.Opt(IDL.Principal),
451
+ memo: IDL.Nat64,
452
+ from_subaccount: IDL.Vec(IDL.Nat8),
453
+ transfer_timestamp: IDL.Nat64,
454
+ block_height: IDL.Nat64
455
+ });
456
+ const KnownNeuronData = IDL.Record({
457
+ name: IDL.Text,
458
+ description: IDL.Opt(IDL.Text)
459
+ });
460
+ const Neuron = IDL.Record({
461
+ id: IDL.Opt(NeuronId),
462
+ staked_maturity_e8s_equivalent: IDL.Opt(IDL.Nat64),
463
+ controller: IDL.Opt(IDL.Principal),
464
+ recent_ballots: IDL.Vec(BallotInfo),
465
+ kyc_verified: IDL.Bool,
466
+ not_for_profit: IDL.Bool,
467
+ maturity_e8s_equivalent: IDL.Nat64,
468
+ cached_neuron_stake_e8s: IDL.Nat64,
469
+ created_timestamp_seconds: IDL.Nat64,
470
+ auto_stake_maturity: IDL.Opt(IDL.Bool),
471
+ aging_since_timestamp_seconds: IDL.Nat64,
472
+ hot_keys: IDL.Vec(IDL.Principal),
473
+ account: IDL.Vec(IDL.Nat8),
474
+ joined_community_fund_timestamp_seconds: IDL.Opt(IDL.Nat64),
475
+ dissolve_state: IDL.Opt(DissolveState),
476
+ followees: IDL.Vec(IDL.Tuple(IDL.Int32, Followees)),
477
+ neuron_fees_e8s: IDL.Nat64,
478
+ transfer: IDL.Opt(NeuronStakeTransfer),
479
+ known_neuron_data: IDL.Opt(KnownNeuronData),
480
+ spawn_at_timestamp_seconds: IDL.Opt(IDL.Nat64)
481
+ });
482
+ const GovernanceError = IDL.Record({
483
+ error_message: IDL.Text,
484
+ error_type: IDL.Int32
485
+ });
486
+ const Result = IDL.Variant({ Ok: Neuron, Err: GovernanceError });
487
+ return IDL.decode([Result], response)[0];
488
+ default:
489
+ throw new errors_1.UnsupportedError(coinlib_core_1.Domain.ICP, `Decode response for action type ${actionType} is not supported`);
490
+ }
491
+ }
394
492
  // DELEGATION
395
493
  getDefaultDelegatee() {
396
494
  var _a, _b, _c;
@@ -400,13 +498,7 @@ class ICPProtocolImpl {
400
498
  return (id === null || id === void 0 ? void 0 : id.toString()) || '';
401
499
  });
402
500
  }
403
- getCurrentDelegateesForPublicKey(publicKey) {
404
- return __awaiter(this, void 0, void 0, function* () {
405
- const address = yield this.getAddressFromPublicKey(publicKey);
406
- return this.getCurrentDelegateesForAddress(address);
407
- });
408
- }
409
- getCurrentDelegateesForAddress(address) {
501
+ getCurrentDelegateesForPublicKey(publicKey, data) {
410
502
  return __awaiter(this, void 0, void 0, function* () {
411
503
  // Fetch neurons of address from governance canister (listNeurons)
412
504
  // Fetch followees from each neuron (get_full_neuron_by_id_or_subaccount)
@@ -414,65 +506,88 @@ class ICPProtocolImpl {
414
506
  return [];
415
507
  });
416
508
  }
417
- getDelegateeDetails(address) {
418
- var _a, _b;
509
+ getCurrentDelegateesForAddress(_address, _data) {
419
510
  return __awaiter(this, void 0, void 0, function* () {
420
- const neuron = yield (0, ICPImplementation_1.getNeuronInfo)(address, this.options.network.rpcUrl, this.options.network.governanceCanisterId);
421
- return {
422
- name: ((_b = (_a = neuron === null || neuron === void 0 ? void 0 : neuron.known_neuron_data) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.name) || '',
423
- address: address
424
- };
511
+ throw new errors_1.UnsupportedError(coinlib_core_1.Domain.ICP, '`getCurrentDelegateesForAddress` is not supported');
425
512
  });
426
513
  }
427
- isPublicKeyDelegating(publicKey) {
514
+ getDelegateeDetails(address, data) {
515
+ var _a, _b, _c, _d;
428
516
  return __awaiter(this, void 0, void 0, function* () {
429
- const address = yield this.getAddressFromPublicKey(publicKey);
430
- return this.isAddressDelegating(address);
517
+ const partialNeuron = yield (0, ICPImplementation_1.getNeuronInfo)(address, this.options.network.rpcUrl, this.options.network.governanceCanisterId);
518
+ const neuronFolowees = (data === null || data === void 0 ? void 0 : data.neuron) ? this.getNeuronFollowees(data.neuron) : undefined;
519
+ return {
520
+ name: ((_b = (_a = partialNeuron === null || partialNeuron === void 0 ? void 0 : partialNeuron.known_neuron_data) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.name) || '',
521
+ address: address,
522
+ status: neuronFolowees ? (neuronFolowees.includes(address) ? 'followed' : 'not-followed') : 'unknown',
523
+ votingPower: (_d = (_c = partialNeuron === null || partialNeuron === void 0 ? void 0 : partialNeuron.voting_power) === null || _c === void 0 ? void 0 : _c.toString()) !== null && _d !== void 0 ? _d : '0'
524
+ };
431
525
  });
432
526
  }
433
- isAddressDelegating(address) {
527
+ isPublicKeyDelegating(publicKey, data) {
528
+ var _a, _b;
434
529
  return __awaiter(this, void 0, void 0, function* () {
435
- // Fetch neurons of address from governance canister (listNeurons)
436
- // Fetch followees from each neuron (get_full_neuron_by_id_or_subaccount)
437
- // If each neuron as followes then it is delegating
438
- // If no neuron has followes then it is not delegating
439
- // If some, but not all, neurons have followes then it is partially delegating
440
- return false;
530
+ const partialNeuron = yield this.getNeuron(publicKey);
531
+ if (partialNeuron === undefined) {
532
+ return false;
533
+ }
534
+ const neuron = data === null || data === void 0 ? void 0 : data.neuron;
535
+ // This case is valid for the `undelegated`/`delegated` badge in
536
+ // without full neuron data we can't be sure if we're actually delegating,
537
+ // i.e. the neuron has followees
538
+ // should we return `true` or `false` here?
539
+ if (neuron === undefined) {
540
+ return true;
541
+ }
542
+ // We should check if partial and full neuron data describe the same neuron
543
+ // but there's no neuron ID in partial neuron data
544
+ if (((_a = partialNeuron.known_neuron_data[0]) === null || _a === void 0 ? void 0 : _a.name) !== ((_b = neuron.known_neuron_data[0]) === null || _b === void 0 ? void 0 : _b.name)) {
545
+ return true;
546
+ }
547
+ return this.getNeuronFollowees(neuron).length > 0;
441
548
  });
442
549
  }
443
- getDelegatorDetailsFromPublicKey(publicKey) {
550
+ isAddressDelegating(_address, data) {
444
551
  return __awaiter(this, void 0, void 0, function* () {
445
- const address = yield this.getAddressFromPublicKey(publicKey);
446
- return this.getDelegatorDetailsFromAddress(address);
552
+ throw new errors_1.UnsupportedError(coinlib_core_1.Domain.ICP, '`isAddressDelegating` is not supported');
447
553
  });
448
554
  }
449
- getDelegatorDetailsFromAddress(address) {
555
+ getDelegatorDetailsFromPublicKey(publicKey, data) {
556
+ var _a, _b, _c, _d;
450
557
  return __awaiter(this, void 0, void 0, function* () {
451
- const metadata = yield this.getMetadata();
558
+ const address = yield this.getAddressFromPublicKey(publicKey);
452
559
  const availableBalance = yield this.getBalanceOfAddress(address);
453
- const availableActions = yield this.getAvailableDelegatorActions();
454
- const totalBalance = (0, module_kit_1.newAmount)(availableBalance.total).blockchain(metadata.units);
560
+ const followees = (data === null || data === void 0 ? void 0 : data.neuron) ? this.getNeuronFollowees(data.neuron) : [];
561
+ const availableActions = yield this.getAvailableDelegatorActions(publicKey, data === null || data === void 0 ? void 0 : data.neuron);
562
+ const neuronBalance = yield this.getNeuronBalance(publicKey);
563
+ const partialNeuron = yield this.getNeuron(publicKey);
564
+ const totalBalance = (0, module_kit_1.newAmount)(availableBalance.total).blockchain(this.units);
565
+ const subaccountBalance = (0, module_kit_1.newAmount)(neuronBalance.total).blockchain(this.units);
455
566
  return {
456
567
  address,
457
568
  balance: totalBalance.value,
458
- delegatees: [],
459
- availableActions: availableActions
569
+ delegatees: followees,
570
+ availableActions: availableActions,
571
+ subaccountBalance: subaccountBalance.value,
572
+ stake: (_a = partialNeuron === null || partialNeuron === void 0 ? void 0 : partialNeuron.stake_e8s) === null || _a === void 0 ? void 0 : _a.toString(),
573
+ votingPower: (_b = partialNeuron === null || partialNeuron === void 0 ? void 0 : partialNeuron.voting_power) === null || _b === void 0 ? void 0 : _b.toString(),
574
+ age: (_c = partialNeuron === null || partialNeuron === void 0 ? void 0 : partialNeuron.age_seconds) === null || _c === void 0 ? void 0 : _c.toString(),
575
+ dissolveDelay: (_d = partialNeuron === null || partialNeuron === void 0 ? void 0 : partialNeuron.dissolve_delay_seconds) === null || _d === void 0 ? void 0 : _d.toString()
460
576
  };
461
577
  });
462
578
  }
463
- getDelegationDetailsFromPublicKey(publicKey, delegatees) {
579
+ getDelegatorDetailsFromAddress(_address, data) {
464
580
  return __awaiter(this, void 0, void 0, function* () {
465
- const address = yield this.getAddressFromPublicKey(publicKey);
466
- return this.getDelegationDetailsFromAddress(address, delegatees);
581
+ throw new errors_1.UnsupportedError(coinlib_core_1.Domain.ICP, '`getDelegatorDetailsFromAddress` is not supported');
467
582
  });
468
583
  }
469
- getDelegationDetailsFromAddress(address, delegatees) {
584
+ getDelegationDetailsFromPublicKey(publicKey, delegatees, data) {
470
585
  return __awaiter(this, void 0, void 0, function* () {
471
586
  if (delegatees.length > 1) {
472
587
  return Promise.reject('Multiple validators for a single delegation are not supported.');
473
588
  }
474
589
  const validator = delegatees[0];
475
- const results = yield Promise.all([this.getDelegatorDetailsFromAddress(address), this.getDelegateeDetails(validator)]);
590
+ const results = yield Promise.all([this.getDelegatorDetailsFromPublicKey(publicKey, data), this.getDelegateeDetails(validator, data)]);
476
591
  const delegatorDetails = results[0];
477
592
  const validatorDetails = results[1];
478
593
  return {
@@ -481,110 +596,218 @@ class ICPProtocolImpl {
481
596
  };
482
597
  });
483
598
  }
484
- getAvailableDelegatorActions() {
599
+ getDelegationDetailsFromAddress(_address, _delegatees, _data) {
600
+ return __awaiter(this, void 0, void 0, function* () {
601
+ throw new errors_1.UnsupportedError(coinlib_core_1.Domain.ICP, '`getDelegationDetailsFromAddress` is not supported');
602
+ });
603
+ }
604
+ getAvailableDelegatorActions(publicKey, fullNeuron) {
485
605
  return __awaiter(this, void 0, void 0, function* () {
486
606
  const actions = [];
487
- actions.push({
488
- type: transaction_1.ICPActionType.GET_NEURON_INFO
489
- });
490
- actions.push({
491
- type: transaction_1.ICPActionType.TRANSFER_TO_SUBACCOUNT,
492
- args: ['amount']
493
- });
494
- actions.push({
495
- type: transaction_1.ICPActionType.CLAIM_GOVERNANCE
496
- });
497
- actions.push({
498
- type: transaction_1.ICPActionType.INCREASE_DELAY,
499
- args: ['delaySeconds']
500
- });
501
- actions.push({
502
- type: transaction_1.ICPActionType.START_DISSOLVING
503
- });
504
- actions.push({
505
- type: transaction_1.ICPActionType.STOP_DISSOLVING
506
- });
507
- actions.push({
508
- type: transaction_1.ICPActionType.FOLLOW_NEURON,
509
- args: ['neuronId']
510
- });
511
- actions.push({
512
- type: transaction_1.ICPActionType.RESTAKE_MATURITY,
513
- args: ['percentageStake']
514
- });
515
- actions.push({
516
- type: transaction_1.ICPActionType.REMOVE_STAKE
517
- });
607
+ const neuronBalance = yield this.getNeuronBalance(publicKey);
608
+ const partialNeuron = yield this.getNeuron(publicKey);
609
+ const isStaking = new bignumber_1.default(neuronBalance.total.value).gt(0);
610
+ const hasNeuron = partialNeuron !== undefined;
611
+ const isNeuronUpToDate = hasNeuron && partialNeuron.stake_e8s.toString() === (0, module_kit_1.newAmount)(neuronBalance.total).blockchain(this.units).value;
612
+ const isFollowing = fullNeuron ? this.getNeuronFollowees(fullNeuron).length > 0 : false;
613
+ const isDissolving = fullNeuron ? this.isNeuronDissolving(fullNeuron) : false;
614
+ const canDisburse = partialNeuron ? this.canNeuronDisburse(partialNeuron) : false;
615
+ if (!isStaking && !hasNeuron) {
616
+ actions.push({
617
+ type: governance_1.ICPStakingActionType.CREATE_NEURON,
618
+ args: ['followee', 'amount', 'delay']
619
+ });
620
+ }
621
+ if (isStaking && !hasNeuron) {
622
+ actions.push({
623
+ type: governance_1.ICPStakingActionType.CLAIM_GOVERNANCE,
624
+ args: ['followee', 'amount', 'delay']
625
+ });
626
+ }
627
+ if (!isNeuronUpToDate) {
628
+ actions.push({
629
+ type: governance_1.ICPStakingActionType.REFRESH_NEURON,
630
+ args: ['amount']
631
+ });
632
+ }
633
+ if (isNeuronUpToDate && fullNeuron === undefined) {
634
+ actions.push({
635
+ type: governance_1.ICPStakingActionType.INCREASE_STAKE,
636
+ args: ['amount']
637
+ });
638
+ }
639
+ if (isNeuronUpToDate && !isFollowing && fullNeuron !== undefined) {
640
+ actions.push({
641
+ type: governance_1.ICPStakingActionType.FOLLOW_NEURON,
642
+ args: ['followee', 'amount', 'delay']
643
+ });
644
+ }
645
+ if (isFollowing && fullNeuron !== undefined) {
646
+ actions.push({
647
+ type: governance_1.ICPStakingActionType.CHANGE_FOLLOWEE,
648
+ args: ['followee', 'amount', 'delay']
649
+ });
650
+ }
651
+ if (hasNeuron) {
652
+ actions.push({
653
+ type: governance_1.ICPStakingActionType.GET_STAKING_DETAILS
654
+ });
655
+ }
656
+ if (isStaking && hasNeuron && !isDissolving && fullNeuron !== undefined) {
657
+ actions.push({
658
+ type: governance_1.ICPStakingActionType.INCREASE_DISSOLVING_DELAY
659
+ }, {
660
+ type: governance_1.ICPStakingActionType.START_DISSOLVING
661
+ });
662
+ }
663
+ if (isDissolving) {
664
+ actions.push({
665
+ type: governance_1.ICPStakingActionType.STOP_DISSOLVING
666
+ });
667
+ }
668
+ if (canDisburse) {
669
+ actions.push({
670
+ type: governance_1.ICPStakingActionType.DISBURSE
671
+ });
672
+ }
518
673
  return actions;
519
674
  });
520
675
  }
521
676
  prepareDelegatorActionFromPublicKey(publicKey, type, data) {
522
677
  return __awaiter(this, void 0, void 0, function* () {
523
678
  switch (type) {
524
- case transaction_1.ICPActionType.GET_NEURON_INFO:
525
- return [yield (0, ICPGovernance_1.createUnsignedTransactionGetNeuronInfo)()];
526
- case transaction_1.ICPActionType.TRANSFER_TO_SUBACCOUNT:
527
- // TODO : get amount from data and fee form defaults
528
- const amount = BigInt(0);
529
- const fee = BigInt(0);
530
- return [yield (0, ICPGovernance_1.createUnsignedTransactionTransferToSubaccount)(publicKey.value, this.options.network.ledgerCanisterId, amount, fee)];
531
- case transaction_1.ICPActionType.CLAIM_GOVERNANCE:
532
- return [yield (0, ICPGovernance_1.createUnsignedTransactionClaimGovernance)(publicKey.value)];
533
- case transaction_1.ICPActionType.INCREASE_DELAY:
534
- // TODO : get delaySeconds from data
535
- const delaySeconds = 0;
536
- return [yield (0, ICPGovernance_1.createUnsignedTransactionIncreaseDelay)(publicKey.value, delaySeconds)];
537
- case transaction_1.ICPActionType.START_DISSOLVING:
538
- return [yield (0, ICPGovernance_1.createUnsignedTransactionStartDissolving)(publicKey.value)];
539
- case transaction_1.ICPActionType.STOP_DISSOLVING:
540
- return [yield (0, ICPGovernance_1.createUnsignedTransactionStopDissolving)(publicKey.value)];
541
- case transaction_1.ICPActionType.FOLLOW_NEURON:
542
- // TODO : get neuronId from data
543
- const neuronId = 0;
544
- return [yield (0, ICPGovernance_1.createUnsignedTransactionFollowNeuron)(publicKey.value, neuronId)];
545
- case transaction_1.ICPActionType.RESTAKE_MATURITY:
546
- // TODO : get percentageStake from data
547
- const percentageStake = 0;
548
- return [yield (0, ICPGovernance_1.createUnsignedTransactionRestakeMaturity)(publicKey.value, percentageStake)];
549
- case transaction_1.ICPActionType.REMOVE_STAKE:
550
- return [yield (0, ICPGovernance_1.createUnsignedTransactionRemoveStake)(publicKey.value)];
679
+ case governance_1.ICPStakingActionType.CREATE_NEURON:
680
+ case governance_1.ICPStakingActionType.INCREASE_STAKE:
681
+ (0, assert_1.assertFields)(`${type} action`, data, 'amount');
682
+ return this.prepareTransferToNeuron(publicKey, data.amount);
683
+ case governance_1.ICPStakingActionType.CLAIM_GOVERNANCE:
684
+ case governance_1.ICPStakingActionType.REFRESH_NEURON:
685
+ (0, assert_1.assertFields)(`${type} action`, data, 'amount');
686
+ return this.prepareClaimOrRefreshNeuron(publicKey, data.amount);
687
+ case governance_1.ICPStakingActionType.GET_STAKING_DETAILS:
688
+ return this.prepareGetStakingDetails();
689
+ case governance_1.ICPStakingActionType.START_DISSOLVING:
690
+ return this.prepareStartDissolving(publicKey);
691
+ case governance_1.ICPStakingActionType.DISBURSE:
692
+ return this.prepareDisburse(publicKey);
551
693
  default:
552
694
  return Promise.reject(`Delegator action type ${type} is not supported.`);
553
695
  }
554
696
  });
555
697
  }
556
- fetchValidators() {
698
+ prepareTransferToNeuron(publicKey, amount) {
557
699
  return __awaiter(this, void 0, void 0, function* () {
558
- return (0, ICPImplementation_1.listKnownNeurons)(this.options.network.rpcUrl, this.options.network.governanceCanisterId);
700
+ const amountBigInt = BigInt(amount);
701
+ const feeBigInt = BigInt((0, module_kit_1.newAmount)(this.feeDefaults.medium).blockchain(this.units).value);
702
+ return [
703
+ (0, module_kit_1.newUnsignedTransaction)({
704
+ transactions: yield Promise.all([
705
+ (0, ICPGovernance_1.prepareTransferToSubaccount)(publicKey.value, this.options.network.governanceCanisterId, amountBigInt, feeBigInt),
706
+ (0, ICPGovernance_1.prepareClaimOrRefreshNeuron)(publicKey.value)
707
+ ])
708
+ })
709
+ ];
710
+ });
711
+ }
712
+ prepareClaimOrRefreshNeuron(publicKey, amount) {
713
+ return __awaiter(this, void 0, void 0, function* () {
714
+ const amountBigInt = BigInt(amount);
715
+ const feeBigInt = BigInt((0, module_kit_1.newAmount)(this.feeDefaults.medium).blockchain(this.units).value);
716
+ return [
717
+ (0, module_kit_1.newUnsignedTransaction)({
718
+ transactions: (yield Promise.all([
719
+ amountBigInt > 0
720
+ ? (0, ICPGovernance_1.prepareTransferToSubaccount)(publicKey.value, this.options.network.governanceCanisterId, amountBigInt, feeBigInt)
721
+ : Promise.resolve(undefined),
722
+ (0, ICPGovernance_1.prepareClaimOrRefreshNeuron)(publicKey.value)
723
+ ])).filter((tx) => tx !== undefined)
724
+ })
725
+ ];
726
+ });
727
+ }
728
+ prepareGetStakingDetails() {
729
+ return __awaiter(this, void 0, void 0, function* () {
730
+ return [
731
+ (0, module_kit_1.newUnsignedTransaction)({
732
+ transactions: [yield (0, ICPGovernance_1.prepareGetNeuronInfo)()]
733
+ })
734
+ ];
559
735
  });
560
736
  }
561
- fetchVotingPower(neuronId) {
737
+ prepareStartDissolving(publicKey) {
562
738
  return __awaiter(this, void 0, void 0, function* () {
563
- const neuron = yield (0, ICPImplementation_1.getNeuronInfo)(neuronId, this.options.network.rpcUrl, this.options.network.governanceCanisterId);
564
- if (neuron) {
565
- return new bignumber_1.default(neuron.voting_power.toString()).div(new bignumber_1.default(10 ** this.units.ICP.decimals));
566
- }
567
- else
568
- return new bignumber_1.default(0);
739
+ return [
740
+ (0, module_kit_1.newUnsignedTransaction)({
741
+ transactions: [yield (0, ICPGovernance_1.prepareStartDissolving)(publicKey.value)]
742
+ })
743
+ ];
744
+ });
745
+ }
746
+ prepareDisburse(publicKey) {
747
+ return __awaiter(this, void 0, void 0, function* () {
748
+ return [
749
+ (0, module_kit_1.newUnsignedTransaction)({
750
+ transactions: [yield (0, ICPGovernance_1.prepareDisburse)(publicKey.value)]
751
+ })
752
+ ];
753
+ });
754
+ }
755
+ getMaxStakingAmount(publicKey) {
756
+ var _a, _b;
757
+ return __awaiter(this, void 0, void 0, function* () {
758
+ const balance = yield this.getBalanceOfPublicKey(publicKey);
759
+ const { subAccount } = (0, ICPImplementation_1.getFixedSubaccountFromPublicKey)(publicKey.value);
760
+ const accountIdentifier = account_1.AccountIdentifier.fromPrincipal({
761
+ principal: principal_1.Principal.from(this.options.network.ledgerCanisterId),
762
+ subAccount: subAccount
763
+ });
764
+ const fee = yield this.getTransactionFeeWithPublicKey(publicKey, [
765
+ {
766
+ to: accountIdentifier.toHex(),
767
+ amount: (_a = balance.transferable) !== null && _a !== void 0 ? _a : balance.total
768
+ }
769
+ ]);
770
+ const maxAmount = (0, module_kit_1.newAmount)((_b = balance.transferable) !== null && _b !== void 0 ? _b : balance.total)
771
+ .blockchain(this.units)
772
+ .toBigNumber()
773
+ .minus((0, module_kit_1.newAmount)(fee).blockchain(this.units).value);
774
+ return (0, module_kit_1.newAmount)(maxAmount, 'blockchain');
569
775
  });
570
776
  }
571
- fetchNeuron(publicKey) {
777
+ getKnownNeurons() {
572
778
  return __awaiter(this, void 0, void 0, function* () {
573
- const neuron = yield (0, ICPImplementation_1.getNeuronInfoBySubAccount)(publicKey, this.options.network.rpcUrl, this.options.network.governanceCanisterId);
779
+ return (0, ICPImplementation_1.listKnownNeurons)(this.options.network.rpcUrl, this.options.network.governanceCanisterId);
780
+ });
781
+ }
782
+ getNeuron(publicKey) {
783
+ return __awaiter(this, void 0, void 0, function* () {
784
+ const neuron = yield (0, ICPImplementation_1.getNeuronInfoBySubAccount)(publicKey.value, this.options.network.rpcUrl, this.options.network.governanceCanisterId);
574
785
  return neuron;
575
786
  });
576
787
  }
577
- fetchSubaccountBalance(publicKey) {
788
+ getNeuronBalance(publicKey) {
578
789
  return __awaiter(this, void 0, void 0, function* () {
579
790
  // Create subaccount from publicKey
580
- const { subAccount, nonce: _ } = (0, ICPImplementation_1.getFixedSubaccountFromPublicKey)(publicKey);
791
+ const { subAccount, nonce: _ } = (0, ICPImplementation_1.getFixedSubaccountFromPublicKey)(publicKey.value);
581
792
  const accountIdentifier = account_1.AccountIdentifier.fromPrincipal({
582
- principal: principal_1.Principal.from(this.options.network.ledgerCanisterId),
793
+ principal: principal_1.Principal.from(this.options.network.governanceCanisterId),
583
794
  subAccount: subAccount
584
795
  });
585
796
  return this.getBalanceOfAddress(accountIdentifier.toHex());
586
797
  });
587
798
  }
799
+ getNeuronFollowees(neuron) {
800
+ return (0, array_1.flattenArray)(neuron.followees.map(([_, { followees }]) => followees.map(({ id }) => id.toString())));
801
+ }
802
+ isNeuronDissolving(neuron) {
803
+ const dissolveState = neuron.dissolve_state[0];
804
+ return (dissolveState !== undefined &&
805
+ 'WhenDissolvedTimestampSeconds' in dissolveState &&
806
+ dissolveState.WhenDissolvedTimestampSeconds > BigInt(0));
807
+ }
808
+ canNeuronDisburse(neuron) {
809
+ return neuron.dissolve_delay_seconds === BigInt(0) && neuron.stake_e8s > BigInt(0);
810
+ }
588
811
  }
589
812
  exports.ICPProtocolImpl = ICPProtocolImpl;
590
813
  // Factory