@xchainjs/xchain-thorchain 0.20.1 → 0.22.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,56 @@
1
+ # v0.22.0 (2022-02-06)
2
+
3
+ ## Add
4
+
5
+ - Option to pass `ChainIds` into constructor
6
+ - getter / setter for `chainId` in `Client`
7
+
8
+ ## Breaking change
9
+
10
+ - `buildDepositTx` needs `chainId` to be passed - all params are set as object
11
+ - Remove `enum ChainId` + `getChainId` + `isChainId` from `utils`
12
+
13
+ # v0.21.2 (2022-02-04)
14
+
15
+ ## Fix
16
+
17
+ - Use latest axios@0.25.0
18
+ - xchain-client@0.11.1
19
+ - @xchainjs/xchain-util@0.5.1
20
+ - @xchainjs/xchain-cosmos@0.16.1
21
+
22
+ # v.0.21.1 (2022-02-04)
23
+
24
+ ## Fix
25
+
26
+ - Fix chain id for `testnet` #477
27
+
28
+ ## Add
29
+
30
+ - Helper `isChainId`
31
+ - `enum ChainId`
32
+
33
+ # v.0.21.0 (2022-02-02)
34
+
35
+ ## Breaking change
36
+
37
+ - Remove `getDenomWithChain`
38
+ - Rename `getAsset` -> `assetFromDenom` (incl. fix to get synth asset properly)
39
+
40
+ ## Update
41
+
42
+ - xchain-util@0.5.0
43
+ - xchain-cosmos@0.16.0
44
+
45
+ ## Add
46
+
47
+ - `isAssetNativeRune` helper
48
+ - Add `TxOfflineParams` type
49
+
50
+ ## Fix
51
+
52
+ - Fix synth notation in `transfer|transferOffline|deposit` #473
53
+
1
54
  # v0.20.1 (2022-01-11)
2
55
 
3
56
  ## Fix
package/lib/client.d.ts CHANGED
@@ -1,9 +1,9 @@
1
1
  import { Address, Balance, Fees, Network, Tx, TxHash, TxHistoryParams, TxParams, TxsPage, XChainClient, XChainClientParams } from '@xchainjs/xchain-client';
2
- import { CosmosSDKClient, RPCTxResult, TxOfflineParams } from '@xchainjs/xchain-cosmos';
2
+ import { CosmosSDKClient, RPCTxResult } from '@xchainjs/xchain-cosmos';
3
3
  import { Asset } from '@xchainjs/xchain-util';
4
4
  import { PrivKey, PubKey } from 'cosmos-client';
5
5
  import { StdTx } from 'cosmos-client/x/auth';
6
- import { ClientUrl, DepositParam, ExplorerUrls, NodeUrl, ThorchainClientParams } from './types';
6
+ import { ChainId, ClientUrl, DepositParam, ExplorerUrls, NodeUrl, ThorchainClientParams, TxOfflineParams } from './types';
7
7
  /**
8
8
  * Interface for custom Thorchain client
9
9
  */
@@ -21,6 +21,7 @@ declare class Client implements ThorchainClient, XChainClient {
21
21
  private network;
22
22
  private clientUrl;
23
23
  private explorerUrls;
24
+ private chainIds;
24
25
  private phrase;
25
26
  private rootDerivationPaths;
26
27
  private cosmosClient;
@@ -34,7 +35,7 @@ declare class Client implements ThorchainClient, XChainClient {
34
35
  *
35
36
  * @throws {"Invalid phrase"} Thrown if the given phase is invalid.
36
37
  */
37
- constructor({ network, phrase, clientUrl, explorerUrls, rootDerivationPaths, }: XChainClientParams & ThorchainClientParams);
38
+ constructor({ network, phrase, clientUrl, explorerUrls, rootDerivationPaths, chainIds, }: XChainClientParams & ThorchainClientParams);
38
39
  /**
39
40
  * Purge client.
40
41
  *
@@ -83,6 +84,23 @@ declare class Client implements ThorchainClient, XChainClient {
83
84
  * @returns {string} The explorer url for thorchain based on the current network.
84
85
  */
85
86
  getExplorerUrl(): string;
87
+ /**
88
+ * Sets chain id
89
+ *
90
+ * @param {ChainId} chainId Chain id to update
91
+ * @param {Network} network (optional) Network for given chainId. If `network`not set, current network of the client is used
92
+ *
93
+ * @returns {void}
94
+ */
95
+ setChainId(chainId: ChainId, network?: Network): void;
96
+ /**
97
+ * Gets chain id
98
+ *
99
+ * @param {Network} network (optional) Network to get chain id from. If `network`not set, current network of the client is used
100
+ *
101
+ * @returns {ChainId} Chain id based on the current network.
102
+ */
103
+ getChainId(network?: Network): ChainId;
86
104
  /**
87
105
  * Get cosmos client
88
106
  * @returns {CosmosSDKClient} current cosmos client
@@ -212,7 +230,7 @@ declare class Client implements ThorchainClient, XChainClient {
212
230
  * @param {TxOfflineParams} params The transfer offline options.
213
231
  * @returns {StdTx} The signed transaction.
214
232
  */
215
- transferOffline({ walletIndex, asset, amount, recipient, memo, from_balance, from_account_number, from_sequence, }: TxOfflineParams): Promise<StdTx>;
233
+ transferOffline({ walletIndex, asset, amount, recipient, memo, from_rune_balance, from_asset_balance, from_account_number, from_sequence, }: TxOfflineParams): Promise<StdTx>;
216
234
  /**
217
235
  * Get the fees.
218
236
  *
package/lib/index.esm.js CHANGED
@@ -1,7 +1,7 @@
1
- import { Network, TxType, singleFee, FeeType, FeeOption } from '@xchainjs/xchain-client';
1
+ import { Network, TxType, singleFee, FeeType } from '@xchainjs/xchain-client';
2
2
  import { CosmosSDKClient } from '@xchainjs/xchain-cosmos';
3
3
  import { validatePhrase } from '@xchainjs/xchain-crypto';
4
- import { assetToString, AssetRuneNative, Chain, assetFromString, baseAmount } from '@xchainjs/xchain-util';
4
+ import { assetToString, AssetRuneNative, isSynthAsset, assetFromString, baseAmount } from '@xchainjs/xchain-util';
5
5
  import axios from 'axios';
6
6
  import { AccAddress, Msg, codec } from 'cosmos-client';
7
7
  import { StdTx } from 'cosmos-client/x/auth';
@@ -119,24 +119,25 @@ var DEFAULT_GAS_VALUE = '2000000';
119
119
  var DEPOSIT_GAS_VALUE = '500000000';
120
120
  var MAX_TX_COUNT = 100;
121
121
  /**
122
- * Get denomination from Asset
122
+ * Checks whether an asset is `AssetRuneNative`
123
123
  *
124
124
  * @param {Asset} asset
125
- * @returns {string} The denomination of the given asset.
125
+ * @returns {boolean} `true` or `false`
126
126
  */
127
- var getDenom = function (asset) {
128
- if (assetToString(asset) === assetToString(AssetRuneNative))
129
- return 'rune';
130
- return asset.symbol;
131
- };
127
+ var isAssetRuneNative = function (asset) { return assetToString(asset) === assetToString(AssetRuneNative); };
128
+ var DENOM_RUNE_NATIVE = 'rune';
132
129
  /**
133
- * Get denomination with chainname from Asset
130
+ * Get denomination from Asset
134
131
  *
135
132
  * @param {Asset} asset
136
- * @returns {string} The denomination with chainname of the given asset.
133
+ * @returns {string} The denomination of the given asset.
137
134
  */
138
- var getDenomWithChain = function (asset) {
139
- return Chain.THORChain + "." + asset.symbol.toUpperCase();
135
+ var getDenom = function (asset) {
136
+ if (isAssetRuneNative(asset))
137
+ return DENOM_RUNE_NATIVE;
138
+ if (isSynthAsset(asset))
139
+ return assetToString(asset).toLowerCase();
140
+ return asset.symbol.toLowerCase();
140
141
  };
141
142
  /**
142
143
  * Get Asset from denomination
@@ -144,10 +145,10 @@ var getDenomWithChain = function (asset) {
144
145
  * @param {string} denom
145
146
  * @returns {Asset|null} The asset of the given denomination.
146
147
  */
147
- var getAsset = function (denom) {
148
- if (denom === getDenom(AssetRuneNative))
148
+ var assetFromDenom = function (denom) {
149
+ if (denom === DENOM_RUNE_NATIVE)
149
150
  return AssetRuneNative;
150
- return assetFromString(Chain.THORChain + "." + denom.toUpperCase());
151
+ return assetFromString(denom.toUpperCase());
151
152
  };
152
153
  /**
153
154
  * Type guard for MsgSend
@@ -197,23 +198,6 @@ var getPrefix = function (network) {
197
198
  return 'tthor';
198
199
  }
199
200
  };
200
- /**
201
- * Get the chain id.
202
- *
203
- * @param {Network} network
204
- * @returns {string} The chain id based on the network.
205
- *
206
- */
207
- var getChainId = function (network) {
208
- switch (network) {
209
- case Network.Mainnet:
210
- return 'thorchain';
211
- case Network.Stagenet:
212
- return 'thorchain-stagenet';
213
- case Network.Testnet:
214
- return 'thorchain';
215
- }
216
- };
217
201
  /**
218
202
  * Register Codecs based on the prefix.
219
203
  *
@@ -291,46 +275,52 @@ var getTxType = function (txData, encoding) {
291
275
  /**
292
276
  * Structure StdTx from MsgNativeTx.
293
277
  *
294
- * @param {string} txId The transaction id.
278
+ * @param {MsgNativeTx} msgNativeTx Msg of type `MsgNativeTx`.
279
+ * @param {string} nodeUrl Node url
280
+ * @param {chainId} ChainId Chain id of the network
281
+ *
295
282
  * @returns {Tx} The transaction details of the given transaction id.
296
283
  *
297
284
  * @throws {"Invalid client url"} Thrown if the client url is an invalid one.
298
285
  */
299
- var buildDepositTx = function (msgNativeTx, nodeUrl) { return __awaiter(void 0, void 0, void 0, function () {
300
- var data, chainId, response, fee, unsignedStdTx;
301
- var _a, _b;
302
- return __generator(this, function (_c) {
303
- switch (_c.label) {
304
- case 0: return [4 /*yield*/, axios.get(nodeUrl + "/cosmos/base/tendermint/v1beta1/node_info")];
305
- case 1:
306
- data = (_c.sent()).data;
307
- chainId = data.default_node_info.network;
308
- if (!chainId || !(chainId == 'thorchain' || chainId == 'thorchain-stagenet'))
309
- throw new Error('invalid network');
310
- return [4 /*yield*/, axios.post(nodeUrl + "/thorchain/deposit", {
311
- coins: msgNativeTx.coins,
312
- memo: msgNativeTx.memo,
313
- base_req: {
314
- chain_id: chainId,
315
- from: msgNativeTx.signer,
316
- },
317
- })];
318
- case 2:
319
- response = (_c.sent()).data;
320
- if (!response || !response.value)
321
- throw new Error('Invalid client url');
322
- fee = (_b = (_a = response.value) === null || _a === void 0 ? void 0 : _a.fee) !== null && _b !== void 0 ? _b : { amount: [] };
323
- unsignedStdTx = StdTx.fromJSON({
324
- msg: response.value.msg,
325
- // override fee
326
- fee: __assign(__assign({}, fee), { gas: DEPOSIT_GAS_VALUE }),
327
- signatures: [],
328
- memo: '',
329
- });
330
- return [2 /*return*/, unsignedStdTx];
331
- }
286
+ var buildDepositTx = function (_a) {
287
+ var msgNativeTx = _a.msgNativeTx, nodeUrl = _a.nodeUrl, chainId = _a.chainId;
288
+ return __awaiter(void 0, void 0, void 0, function () {
289
+ var data, networkChainId, response, fee, unsignedStdTx;
290
+ var _b, _c;
291
+ return __generator(this, function (_d) {
292
+ switch (_d.label) {
293
+ case 0: return [4 /*yield*/, axios.get(nodeUrl + "/cosmos/base/tendermint/v1beta1/node_info")];
294
+ case 1:
295
+ data = (_d.sent()).data;
296
+ networkChainId = data.default_node_info.network;
297
+ if (!networkChainId || chainId !== networkChainId)
298
+ throw new Error("Invalid network (asked: " + chainId + " / returned: " + networkChainId);
299
+ return [4 /*yield*/, axios.post(nodeUrl + "/thorchain/deposit", {
300
+ coins: msgNativeTx.coins,
301
+ memo: msgNativeTx.memo,
302
+ base_req: {
303
+ chain_id: chainId,
304
+ from: msgNativeTx.signer,
305
+ },
306
+ })];
307
+ case 2:
308
+ response = (_d.sent()).data;
309
+ if (!response || !response.value)
310
+ throw new Error('Invalid client url');
311
+ fee = (_c = (_b = response.value) === null || _b === void 0 ? void 0 : _b.fee) !== null && _c !== void 0 ? _c : { amount: [] };
312
+ unsignedStdTx = StdTx.fromJSON({
313
+ msg: response.value.msg,
314
+ // override fee
315
+ fee: __assign(__assign({}, fee), { gas: DEPOSIT_GAS_VALUE }),
316
+ signatures: [],
317
+ memo: '',
318
+ });
319
+ return [2 /*return*/, unsignedStdTx];
320
+ }
321
+ });
332
322
  });
333
- }); };
323
+ };
334
324
  /**
335
325
  * Get the balance of a given address.
336
326
  *
@@ -351,7 +341,7 @@ var getBalance = function (_a) {
351
341
  balances = _b.sent();
352
342
  return [2 /*return*/, balances
353
343
  .map(function (balance) { return ({
354
- asset: (balance.denom && getAsset(balance.denom)) || AssetRuneNative,
344
+ asset: (balance.denom && assetFromDenom(balance.denom)) || AssetRuneNative,
355
345
  amount: baseAmount(balance.amount, DECIMAL),
356
346
  }); })
357
347
  .filter(function (balance) { return !assets || assets.filter(function (asset) { return assetToString(balance.asset) === assetToString(asset); }).length; })];
@@ -479,13 +469,17 @@ var Client = /** @class */ (function () {
479
469
  * @throws {"Invalid phrase"} Thrown if the given phase is invalid.
480
470
  */
481
471
  function Client(_a) {
482
- var _b;
472
+ var _b, _c;
483
473
  var _this = this;
484
- var _c = _a.network, network = _c === void 0 ? Network.Testnet : _c, phrase = _a.phrase, clientUrl = _a.clientUrl, explorerUrls = _a.explorerUrls, _d = _a.rootDerivationPaths, rootDerivationPaths = _d === void 0 ? (_b = {},
474
+ var _d = _a.network, network = _d === void 0 ? Network.Testnet : _d, phrase = _a.phrase, clientUrl = _a.clientUrl, explorerUrls = _a.explorerUrls, _e = _a.rootDerivationPaths, rootDerivationPaths = _e === void 0 ? (_b = {},
485
475
  _b[Network.Mainnet] = "44'/931'/0'/0/",
486
476
  _b[Network.Stagenet] = "44'/931'/0'/0/",
487
477
  _b[Network.Testnet] = "44'/931'/0'/0/",
488
- _b) : _d;
478
+ _b) : _e, _f = _a.chainIds, chainIds = _f === void 0 ? (_c = {},
479
+ _c[Network.Mainnet] = 'thorchain',
480
+ _c[Network.Stagenet] = 'thorchain-stagenet',
481
+ _c[Network.Testnet] = 'thorchain-v1',
482
+ _c) : _f;
489
483
  this.phrase = '';
490
484
  /**
491
485
  * Get transaction history of a given address with pagination options.
@@ -555,10 +549,11 @@ var Client = /** @class */ (function () {
555
549
  this.network = network;
556
550
  this.clientUrl = clientUrl || getDefaultClientUrl();
557
551
  this.explorerUrls = explorerUrls || getDefaultExplorerUrls();
552
+ this.chainIds = chainIds;
558
553
  this.rootDerivationPaths = rootDerivationPaths;
559
554
  this.cosmosClient = new CosmosSDKClient({
560
555
  server: this.getClientUrl().node,
561
- chainId: getChainId(this.network),
556
+ chainId: this.getChainId(this.network),
562
557
  prefix: getPrefix(this.network),
563
558
  });
564
559
  if (phrase)
@@ -630,6 +625,28 @@ var Client = /** @class */ (function () {
630
625
  Client.prototype.getExplorerUrl = function () {
631
626
  return this.explorerUrls.root[this.network];
632
627
  };
628
+ /**
629
+ * Sets chain id
630
+ *
631
+ * @param {ChainId} chainId Chain id to update
632
+ * @param {Network} network (optional) Network for given chainId. If `network`not set, current network of the client is used
633
+ *
634
+ * @returns {void}
635
+ */
636
+ Client.prototype.setChainId = function (chainId, network) {
637
+ var _a;
638
+ this.chainIds = __assign(__assign({}, this.chainIds), (_a = {}, _a[network || this.network] = chainId, _a));
639
+ };
640
+ /**
641
+ * Gets chain id
642
+ *
643
+ * @param {Network} network (optional) Network to get chain id from. If `network`not set, current network of the client is used
644
+ *
645
+ * @returns {ChainId} Chain id based on the current network.
646
+ */
647
+ Client.prototype.getChainId = function (network) {
648
+ return this.chainIds[network || this.network];
649
+ };
633
650
  /**
634
651
  * Get cosmos client
635
652
  * @returns {CosmosSDKClient} current cosmos client
@@ -830,36 +847,58 @@ var Client = /** @class */ (function () {
830
847
  * @throws {"failed to broadcast transaction"} Thrown if failed to broadcast transaction.
831
848
  */
832
849
  Client.prototype.deposit = function (_a) {
833
- var _b, _c;
834
- var _d = _a.walletIndex, walletIndex = _d === void 0 ? 0 : _d, _e = _a.asset, asset = _e === void 0 ? AssetRuneNative : _e, amount = _a.amount, memo = _a.memo;
850
+ var _b, _c, _d, _e, _f, _g;
851
+ var _h = _a.walletIndex, walletIndex = _h === void 0 ? 0 : _h, _j = _a.asset, asset = _j === void 0 ? AssetRuneNative : _j, amount = _a.amount, memo = _a.memo;
835
852
  return __awaiter(this, void 0, void 0, function () {
836
- var assetBalance, signer, msgNativeTx, unsignedStdTx, privateKey, accAddress;
837
- return __generator(this, function (_f) {
838
- switch (_f.label) {
839
- case 0: return [4 /*yield*/, this.getBalance(this.getAddress(walletIndex), [asset])];
853
+ var balances, runeBalance, assetBalance, fee, signer, msgNativeTx, unsignedStdTx, privateKey, accAddress;
854
+ return __generator(this, function (_k) {
855
+ switch (_k.label) {
856
+ case 0: return [4 /*yield*/, this.getBalance(this.getAddress(walletIndex))];
840
857
  case 1:
841
- assetBalance = _f.sent();
842
- if (assetBalance.length === 0 || assetBalance[0].amount.amount().lt(amount.amount().plus(DEFAULT_GAS_VALUE))) {
843
- throw new Error('insufficient funds');
858
+ balances = _k.sent();
859
+ runeBalance = (_c = (_b = balances.filter(function (_a) {
860
+ var asset = _a.asset;
861
+ return isAssetRuneNative(asset);
862
+ })[0]) === null || _b === void 0 ? void 0 : _b.amount) !== null && _c !== void 0 ? _c : baseAmount(0, DECIMAL);
863
+ assetBalance = (_e = (_d = balances.filter(function (_a) {
864
+ var assetInList = _a.asset;
865
+ return assetToString(assetInList) === assetToString(asset);
866
+ })[0]) === null || _d === void 0 ? void 0 : _d.amount) !== null && _e !== void 0 ? _e : baseAmount(0, DECIMAL);
867
+ fee = baseAmount(DEFAULT_GAS_VALUE, DECIMAL);
868
+ if (isAssetRuneNative(asset)) {
869
+ // amount + fee < runeBalance
870
+ if (runeBalance.lt(amount.plus(fee))) {
871
+ throw new Error('insufficient funds');
872
+ }
873
+ }
874
+ else {
875
+ // amount < assetBalances && runeBalance < fee
876
+ if (assetBalance.lt(amount) || runeBalance.lt(fee)) {
877
+ throw new Error('insufficient funds');
878
+ }
844
879
  }
845
880
  signer = this.getAddress(walletIndex);
846
881
  msgNativeTx = msgNativeTxFromJson({
847
882
  coins: [
848
883
  {
849
- asset: getDenomWithChain(asset),
884
+ asset: isAssetRuneNative(asset) ? assetToString(AssetRuneNative) : getDenom(asset),
850
885
  amount: amount.amount().toString(),
851
886
  },
852
887
  ],
853
888
  memo: memo,
854
889
  signer: signer,
855
890
  });
856
- return [4 /*yield*/, buildDepositTx(msgNativeTx, this.getClientUrl().node)];
891
+ return [4 /*yield*/, buildDepositTx({
892
+ msgNativeTx: msgNativeTx,
893
+ nodeUrl: this.getClientUrl().node,
894
+ chainId: this.getChainId(),
895
+ })];
857
896
  case 2:
858
- unsignedStdTx = _f.sent();
897
+ unsignedStdTx = _k.sent();
859
898
  privateKey = this.getPrivKey(walletIndex);
860
899
  accAddress = AccAddress.fromBech32(signer);
861
900
  return [4 /*yield*/, this.cosmosClient.signAndBroadcast(unsignedStdTx, privateKey, accAddress)];
862
- case 3: return [2 /*return*/, (_c = (_b = (_f.sent())) === null || _b === void 0 ? void 0 : _b.txhash) !== null && _c !== void 0 ? _c : ''];
901
+ case 3: return [2 /*return*/, (_g = (_f = (_k.sent())) === null || _f === void 0 ? void 0 : _f.txhash) !== null && _g !== void 0 ? _g : ''];
863
902
  }
864
903
  });
865
904
  });
@@ -871,22 +910,39 @@ var Client = /** @class */ (function () {
871
910
  * @returns {TxHash} The transaction hash.
872
911
  */
873
912
  Client.prototype.transfer = function (_a) {
874
- var _b = _a.walletIndex, walletIndex = _b === void 0 ? 0 : _b, _c = _a.asset, asset = _c === void 0 ? AssetRuneNative : _c, amount = _a.amount, recipient = _a.recipient, memo = _a.memo;
913
+ var _b, _c, _d, _e;
914
+ var _f = _a.walletIndex, walletIndex = _f === void 0 ? 0 : _f, _g = _a.asset, asset = _g === void 0 ? AssetRuneNative : _g, amount = _a.amount, recipient = _a.recipient, memo = _a.memo;
875
915
  return __awaiter(this, void 0, void 0, function () {
876
- var assetBalance, fee, transferResult;
877
- return __generator(this, function (_d) {
878
- switch (_d.label) {
916
+ var balances, runeBalance, assetBalance, fee, transferResult;
917
+ return __generator(this, function (_h) {
918
+ switch (_h.label) {
879
919
  case 0:
880
920
  registerCodecs(getPrefix(this.network));
881
- return [4 /*yield*/, this.getBalance(this.getAddress(walletIndex), [asset])];
921
+ return [4 /*yield*/, this.getBalance(this.getAddress(walletIndex))];
882
922
  case 1:
883
- assetBalance = _d.sent();
923
+ balances = _h.sent();
924
+ runeBalance = (_c = (_b = balances.filter(function (_a) {
925
+ var asset = _a.asset;
926
+ return isAssetRuneNative(asset);
927
+ })[0]) === null || _b === void 0 ? void 0 : _b.amount) !== null && _c !== void 0 ? _c : baseAmount(0, DECIMAL);
928
+ assetBalance = (_e = (_d = balances.filter(function (_a) {
929
+ var assetInList = _a.asset;
930
+ return assetToString(assetInList) === assetToString(asset);
931
+ })[0]) === null || _d === void 0 ? void 0 : _d.amount) !== null && _e !== void 0 ? _e : baseAmount(0, DECIMAL);
884
932
  return [4 /*yield*/, this.getFees()];
885
933
  case 2:
886
- fee = _d.sent();
887
- if (assetBalance.length === 0 ||
888
- assetBalance[0].amount.amount().lt(amount.amount().plus(fee[FeeOption.Average].amount()))) {
889
- throw new Error('insufficient funds');
934
+ fee = (_h.sent()).average;
935
+ if (isAssetRuneNative(asset)) {
936
+ // amount + fee < runeBalance
937
+ if (runeBalance.lt(amount.plus(fee))) {
938
+ throw new Error('insufficient funds');
939
+ }
940
+ }
941
+ else {
942
+ // amount < assetBalances && runeBalance < fee
943
+ if (assetBalance.lt(amount) || runeBalance.lt(fee)) {
944
+ throw new Error('insufficient funds');
945
+ }
890
946
  }
891
947
  return [4 /*yield*/, this.cosmosClient.transfer({
892
948
  privkey: this.getPrivKey(walletIndex),
@@ -901,7 +957,7 @@ var Client = /** @class */ (function () {
901
957
  },
902
958
  })];
903
959
  case 3:
904
- transferResult = _d.sent();
960
+ transferResult = _h.sent();
905
961
  if (!isBroadcastSuccess(transferResult)) {
906
962
  throw new Error("failed to broadcast transaction: " + transferResult.txhash);
907
963
  }
@@ -917,7 +973,7 @@ var Client = /** @class */ (function () {
917
973
  * @returns {StdTx} The signed transaction.
918
974
  */
919
975
  Client.prototype.transferOffline = function (_a) {
920
- var _b = _a.walletIndex, walletIndex = _b === void 0 ? 0 : _b, _c = _a.asset, asset = _c === void 0 ? AssetRuneNative : _c, amount = _a.amount, recipient = _a.recipient, memo = _a.memo, _d = _a.from_balance, from_balance = _d === void 0 ? baseAmount('0', DECIMAL) : _d, _e = _a.from_account_number, from_account_number = _e === void 0 ? '0' : _e, _f = _a.from_sequence, from_sequence = _f === void 0 ? '0' : _f;
976
+ var _b = _a.walletIndex, walletIndex = _b === void 0 ? 0 : _b, _c = _a.asset, asset = _c === void 0 ? AssetRuneNative : _c, amount = _a.amount, recipient = _a.recipient, memo = _a.memo, from_rune_balance = _a.from_rune_balance, _d = _a.from_asset_balance, from_asset_balance = _d === void 0 ? baseAmount(0, DECIMAL) : _d, _e = _a.from_account_number, from_account_number = _e === void 0 ? '0' : _e, _f = _a.from_sequence, from_sequence = _f === void 0 ? '0' : _f;
921
977
  return __awaiter(this, void 0, void 0, function () {
922
978
  var fee, result;
923
979
  return __generator(this, function (_g) {
@@ -926,10 +982,18 @@ var Client = /** @class */ (function () {
926
982
  registerCodecs(getPrefix(this.network));
927
983
  return [4 /*yield*/, this.getFees()];
928
984
  case 1:
929
- fee = _g.sent();
930
- if (from_balance === baseAmount('0', DECIMAL) ||
931
- from_balance.amount().lt(amount.amount().plus(fee[FeeOption.Average].amount()))) {
932
- throw new Error('insufficient funds');
985
+ fee = (_g.sent()).average;
986
+ if (isAssetRuneNative(asset)) {
987
+ // amount + fee < runeBalance
988
+ if (from_rune_balance.lt(amount.plus(fee))) {
989
+ throw new Error('insufficient funds');
990
+ }
991
+ }
992
+ else {
993
+ // amount < assetBalances && runeBalance < fee
994
+ if (from_asset_balance.lt(amount) || from_rune_balance.lt(fee)) {
995
+ throw new Error('insufficient funds');
996
+ }
933
997
  }
934
998
  return [4 /*yield*/, this.cosmosClient.transferSignedOffline({
935
999
  privkey: this.getPrivKey(walletIndex),
@@ -967,4 +1031,4 @@ var Client = /** @class */ (function () {
967
1031
  return Client;
968
1032
  }());
969
1033
 
970
- export { Client, DECIMAL, DEFAULT_GAS_VALUE, DEPOSIT_GAS_VALUE, MAX_TX_COUNT, MsgNativeTx, buildDepositTx, getAsset, getBalance, getChainId, getDefaultClientUrl, getDefaultExplorerUrls, getDefaultFees, getDenom, getDenomWithChain, getDepositTxDataFromLogs, getExplorerAddressUrl, getExplorerTxUrl, getExplorerUrl, getPrefix, getTxType, isBroadcastSuccess, isMsgMultiSend, isMsgSend, msgNativeTxFromJson, registerCodecs };
1034
+ export { Client, DECIMAL, DEFAULT_GAS_VALUE, DEPOSIT_GAS_VALUE, MAX_TX_COUNT, MsgNativeTx, assetFromDenom, buildDepositTx, getBalance, getDefaultClientUrl, getDefaultExplorerUrls, getDefaultFees, getDenom, getDepositTxDataFromLogs, getExplorerAddressUrl, getExplorerTxUrl, getExplorerUrl, getPrefix, getTxType, isAssetRuneNative, isBroadcastSuccess, isMsgMultiSend, isMsgSend, msgNativeTxFromJson, registerCodecs };
package/lib/index.js CHANGED
@@ -127,24 +127,25 @@ var DEFAULT_GAS_VALUE = '2000000';
127
127
  var DEPOSIT_GAS_VALUE = '500000000';
128
128
  var MAX_TX_COUNT = 100;
129
129
  /**
130
- * Get denomination from Asset
130
+ * Checks whether an asset is `AssetRuneNative`
131
131
  *
132
132
  * @param {Asset} asset
133
- * @returns {string} The denomination of the given asset.
133
+ * @returns {boolean} `true` or `false`
134
134
  */
135
- var getDenom = function (asset) {
136
- if (xchainUtil.assetToString(asset) === xchainUtil.assetToString(xchainUtil.AssetRuneNative))
137
- return 'rune';
138
- return asset.symbol;
139
- };
135
+ var isAssetRuneNative = function (asset) { return xchainUtil.assetToString(asset) === xchainUtil.assetToString(xchainUtil.AssetRuneNative); };
136
+ var DENOM_RUNE_NATIVE = 'rune';
140
137
  /**
141
- * Get denomination with chainname from Asset
138
+ * Get denomination from Asset
142
139
  *
143
140
  * @param {Asset} asset
144
- * @returns {string} The denomination with chainname of the given asset.
141
+ * @returns {string} The denomination of the given asset.
145
142
  */
146
- var getDenomWithChain = function (asset) {
147
- return xchainUtil.Chain.THORChain + "." + asset.symbol.toUpperCase();
143
+ var getDenom = function (asset) {
144
+ if (isAssetRuneNative(asset))
145
+ return DENOM_RUNE_NATIVE;
146
+ if (xchainUtil.isSynthAsset(asset))
147
+ return xchainUtil.assetToString(asset).toLowerCase();
148
+ return asset.symbol.toLowerCase();
148
149
  };
149
150
  /**
150
151
  * Get Asset from denomination
@@ -152,10 +153,10 @@ var getDenomWithChain = function (asset) {
152
153
  * @param {string} denom
153
154
  * @returns {Asset|null} The asset of the given denomination.
154
155
  */
155
- var getAsset = function (denom) {
156
- if (denom === getDenom(xchainUtil.AssetRuneNative))
156
+ var assetFromDenom = function (denom) {
157
+ if (denom === DENOM_RUNE_NATIVE)
157
158
  return xchainUtil.AssetRuneNative;
158
- return xchainUtil.assetFromString(xchainUtil.Chain.THORChain + "." + denom.toUpperCase());
159
+ return xchainUtil.assetFromString(denom.toUpperCase());
159
160
  };
160
161
  /**
161
162
  * Type guard for MsgSend
@@ -205,23 +206,6 @@ var getPrefix = function (network) {
205
206
  return 'tthor';
206
207
  }
207
208
  };
208
- /**
209
- * Get the chain id.
210
- *
211
- * @param {Network} network
212
- * @returns {string} The chain id based on the network.
213
- *
214
- */
215
- var getChainId = function (network) {
216
- switch (network) {
217
- case xchainClient.Network.Mainnet:
218
- return 'thorchain';
219
- case xchainClient.Network.Stagenet:
220
- return 'thorchain-stagenet';
221
- case xchainClient.Network.Testnet:
222
- return 'thorchain';
223
- }
224
- };
225
209
  /**
226
210
  * Register Codecs based on the prefix.
227
211
  *
@@ -299,46 +283,52 @@ var getTxType = function (txData, encoding) {
299
283
  /**
300
284
  * Structure StdTx from MsgNativeTx.
301
285
  *
302
- * @param {string} txId The transaction id.
286
+ * @param {MsgNativeTx} msgNativeTx Msg of type `MsgNativeTx`.
287
+ * @param {string} nodeUrl Node url
288
+ * @param {chainId} ChainId Chain id of the network
289
+ *
303
290
  * @returns {Tx} The transaction details of the given transaction id.
304
291
  *
305
292
  * @throws {"Invalid client url"} Thrown if the client url is an invalid one.
306
293
  */
307
- var buildDepositTx = function (msgNativeTx, nodeUrl) { return __awaiter(void 0, void 0, void 0, function () {
308
- var data, chainId, response, fee, unsignedStdTx;
309
- var _a, _b;
310
- return __generator(this, function (_c) {
311
- switch (_c.label) {
312
- case 0: return [4 /*yield*/, axios__default['default'].get(nodeUrl + "/cosmos/base/tendermint/v1beta1/node_info")];
313
- case 1:
314
- data = (_c.sent()).data;
315
- chainId = data.default_node_info.network;
316
- if (!chainId || !(chainId == 'thorchain' || chainId == 'thorchain-stagenet'))
317
- throw new Error('invalid network');
318
- return [4 /*yield*/, axios__default['default'].post(nodeUrl + "/thorchain/deposit", {
319
- coins: msgNativeTx.coins,
320
- memo: msgNativeTx.memo,
321
- base_req: {
322
- chain_id: chainId,
323
- from: msgNativeTx.signer,
324
- },
325
- })];
326
- case 2:
327
- response = (_c.sent()).data;
328
- if (!response || !response.value)
329
- throw new Error('Invalid client url');
330
- fee = (_b = (_a = response.value) === null || _a === void 0 ? void 0 : _a.fee) !== null && _b !== void 0 ? _b : { amount: [] };
331
- unsignedStdTx = auth.StdTx.fromJSON({
332
- msg: response.value.msg,
333
- // override fee
334
- fee: __assign(__assign({}, fee), { gas: DEPOSIT_GAS_VALUE }),
335
- signatures: [],
336
- memo: '',
337
- });
338
- return [2 /*return*/, unsignedStdTx];
339
- }
294
+ var buildDepositTx = function (_a) {
295
+ var msgNativeTx = _a.msgNativeTx, nodeUrl = _a.nodeUrl, chainId = _a.chainId;
296
+ return __awaiter(void 0, void 0, void 0, function () {
297
+ var data, networkChainId, response, fee, unsignedStdTx;
298
+ var _b, _c;
299
+ return __generator(this, function (_d) {
300
+ switch (_d.label) {
301
+ case 0: return [4 /*yield*/, axios__default['default'].get(nodeUrl + "/cosmos/base/tendermint/v1beta1/node_info")];
302
+ case 1:
303
+ data = (_d.sent()).data;
304
+ networkChainId = data.default_node_info.network;
305
+ if (!networkChainId || chainId !== networkChainId)
306
+ throw new Error("Invalid network (asked: " + chainId + " / returned: " + networkChainId);
307
+ return [4 /*yield*/, axios__default['default'].post(nodeUrl + "/thorchain/deposit", {
308
+ coins: msgNativeTx.coins,
309
+ memo: msgNativeTx.memo,
310
+ base_req: {
311
+ chain_id: chainId,
312
+ from: msgNativeTx.signer,
313
+ },
314
+ })];
315
+ case 2:
316
+ response = (_d.sent()).data;
317
+ if (!response || !response.value)
318
+ throw new Error('Invalid client url');
319
+ fee = (_c = (_b = response.value) === null || _b === void 0 ? void 0 : _b.fee) !== null && _c !== void 0 ? _c : { amount: [] };
320
+ unsignedStdTx = auth.StdTx.fromJSON({
321
+ msg: response.value.msg,
322
+ // override fee
323
+ fee: __assign(__assign({}, fee), { gas: DEPOSIT_GAS_VALUE }),
324
+ signatures: [],
325
+ memo: '',
326
+ });
327
+ return [2 /*return*/, unsignedStdTx];
328
+ }
329
+ });
340
330
  });
341
- }); };
331
+ };
342
332
  /**
343
333
  * Get the balance of a given address.
344
334
  *
@@ -359,7 +349,7 @@ var getBalance = function (_a) {
359
349
  balances = _b.sent();
360
350
  return [2 /*return*/, balances
361
351
  .map(function (balance) { return ({
362
- asset: (balance.denom && getAsset(balance.denom)) || xchainUtil.AssetRuneNative,
352
+ asset: (balance.denom && assetFromDenom(balance.denom)) || xchainUtil.AssetRuneNative,
363
353
  amount: xchainUtil.baseAmount(balance.amount, DECIMAL),
364
354
  }); })
365
355
  .filter(function (balance) { return !assets || assets.filter(function (asset) { return xchainUtil.assetToString(balance.asset) === xchainUtil.assetToString(asset); }).length; })];
@@ -487,13 +477,17 @@ var Client = /** @class */ (function () {
487
477
  * @throws {"Invalid phrase"} Thrown if the given phase is invalid.
488
478
  */
489
479
  function Client(_a) {
490
- var _b;
480
+ var _b, _c;
491
481
  var _this = this;
492
- var _c = _a.network, network = _c === void 0 ? xchainClient.Network.Testnet : _c, phrase = _a.phrase, clientUrl = _a.clientUrl, explorerUrls = _a.explorerUrls, _d = _a.rootDerivationPaths, rootDerivationPaths = _d === void 0 ? (_b = {},
482
+ var _d = _a.network, network = _d === void 0 ? xchainClient.Network.Testnet : _d, phrase = _a.phrase, clientUrl = _a.clientUrl, explorerUrls = _a.explorerUrls, _e = _a.rootDerivationPaths, rootDerivationPaths = _e === void 0 ? (_b = {},
493
483
  _b[xchainClient.Network.Mainnet] = "44'/931'/0'/0/",
494
484
  _b[xchainClient.Network.Stagenet] = "44'/931'/0'/0/",
495
485
  _b[xchainClient.Network.Testnet] = "44'/931'/0'/0/",
496
- _b) : _d;
486
+ _b) : _e, _f = _a.chainIds, chainIds = _f === void 0 ? (_c = {},
487
+ _c[xchainClient.Network.Mainnet] = 'thorchain',
488
+ _c[xchainClient.Network.Stagenet] = 'thorchain-stagenet',
489
+ _c[xchainClient.Network.Testnet] = 'thorchain-v1',
490
+ _c) : _f;
497
491
  this.phrase = '';
498
492
  /**
499
493
  * Get transaction history of a given address with pagination options.
@@ -563,10 +557,11 @@ var Client = /** @class */ (function () {
563
557
  this.network = network;
564
558
  this.clientUrl = clientUrl || getDefaultClientUrl();
565
559
  this.explorerUrls = explorerUrls || getDefaultExplorerUrls();
560
+ this.chainIds = chainIds;
566
561
  this.rootDerivationPaths = rootDerivationPaths;
567
562
  this.cosmosClient = new xchainCosmos.CosmosSDKClient({
568
563
  server: this.getClientUrl().node,
569
- chainId: getChainId(this.network),
564
+ chainId: this.getChainId(this.network),
570
565
  prefix: getPrefix(this.network),
571
566
  });
572
567
  if (phrase)
@@ -638,6 +633,28 @@ var Client = /** @class */ (function () {
638
633
  Client.prototype.getExplorerUrl = function () {
639
634
  return this.explorerUrls.root[this.network];
640
635
  };
636
+ /**
637
+ * Sets chain id
638
+ *
639
+ * @param {ChainId} chainId Chain id to update
640
+ * @param {Network} network (optional) Network for given chainId. If `network`not set, current network of the client is used
641
+ *
642
+ * @returns {void}
643
+ */
644
+ Client.prototype.setChainId = function (chainId, network) {
645
+ var _a;
646
+ this.chainIds = __assign(__assign({}, this.chainIds), (_a = {}, _a[network || this.network] = chainId, _a));
647
+ };
648
+ /**
649
+ * Gets chain id
650
+ *
651
+ * @param {Network} network (optional) Network to get chain id from. If `network`not set, current network of the client is used
652
+ *
653
+ * @returns {ChainId} Chain id based on the current network.
654
+ */
655
+ Client.prototype.getChainId = function (network) {
656
+ return this.chainIds[network || this.network];
657
+ };
641
658
  /**
642
659
  * Get cosmos client
643
660
  * @returns {CosmosSDKClient} current cosmos client
@@ -838,36 +855,58 @@ var Client = /** @class */ (function () {
838
855
  * @throws {"failed to broadcast transaction"} Thrown if failed to broadcast transaction.
839
856
  */
840
857
  Client.prototype.deposit = function (_a) {
841
- var _b, _c;
842
- var _d = _a.walletIndex, walletIndex = _d === void 0 ? 0 : _d, _e = _a.asset, asset = _e === void 0 ? xchainUtil.AssetRuneNative : _e, amount = _a.amount, memo = _a.memo;
858
+ var _b, _c, _d, _e, _f, _g;
859
+ var _h = _a.walletIndex, walletIndex = _h === void 0 ? 0 : _h, _j = _a.asset, asset = _j === void 0 ? xchainUtil.AssetRuneNative : _j, amount = _a.amount, memo = _a.memo;
843
860
  return __awaiter(this, void 0, void 0, function () {
844
- var assetBalance, signer, msgNativeTx, unsignedStdTx, privateKey, accAddress;
845
- return __generator(this, function (_f) {
846
- switch (_f.label) {
847
- case 0: return [4 /*yield*/, this.getBalance(this.getAddress(walletIndex), [asset])];
861
+ var balances, runeBalance, assetBalance, fee, signer, msgNativeTx, unsignedStdTx, privateKey, accAddress;
862
+ return __generator(this, function (_k) {
863
+ switch (_k.label) {
864
+ case 0: return [4 /*yield*/, this.getBalance(this.getAddress(walletIndex))];
848
865
  case 1:
849
- assetBalance = _f.sent();
850
- if (assetBalance.length === 0 || assetBalance[0].amount.amount().lt(amount.amount().plus(DEFAULT_GAS_VALUE))) {
851
- throw new Error('insufficient funds');
866
+ balances = _k.sent();
867
+ runeBalance = (_c = (_b = balances.filter(function (_a) {
868
+ var asset = _a.asset;
869
+ return isAssetRuneNative(asset);
870
+ })[0]) === null || _b === void 0 ? void 0 : _b.amount) !== null && _c !== void 0 ? _c : xchainUtil.baseAmount(0, DECIMAL);
871
+ assetBalance = (_e = (_d = balances.filter(function (_a) {
872
+ var assetInList = _a.asset;
873
+ return xchainUtil.assetToString(assetInList) === xchainUtil.assetToString(asset);
874
+ })[0]) === null || _d === void 0 ? void 0 : _d.amount) !== null && _e !== void 0 ? _e : xchainUtil.baseAmount(0, DECIMAL);
875
+ fee = xchainUtil.baseAmount(DEFAULT_GAS_VALUE, DECIMAL);
876
+ if (isAssetRuneNative(asset)) {
877
+ // amount + fee < runeBalance
878
+ if (runeBalance.lt(amount.plus(fee))) {
879
+ throw new Error('insufficient funds');
880
+ }
881
+ }
882
+ else {
883
+ // amount < assetBalances && runeBalance < fee
884
+ if (assetBalance.lt(amount) || runeBalance.lt(fee)) {
885
+ throw new Error('insufficient funds');
886
+ }
852
887
  }
853
888
  signer = this.getAddress(walletIndex);
854
889
  msgNativeTx = msgNativeTxFromJson({
855
890
  coins: [
856
891
  {
857
- asset: getDenomWithChain(asset),
892
+ asset: isAssetRuneNative(asset) ? xchainUtil.assetToString(xchainUtil.AssetRuneNative) : getDenom(asset),
858
893
  amount: amount.amount().toString(),
859
894
  },
860
895
  ],
861
896
  memo: memo,
862
897
  signer: signer,
863
898
  });
864
- return [4 /*yield*/, buildDepositTx(msgNativeTx, this.getClientUrl().node)];
899
+ return [4 /*yield*/, buildDepositTx({
900
+ msgNativeTx: msgNativeTx,
901
+ nodeUrl: this.getClientUrl().node,
902
+ chainId: this.getChainId(),
903
+ })];
865
904
  case 2:
866
- unsignedStdTx = _f.sent();
905
+ unsignedStdTx = _k.sent();
867
906
  privateKey = this.getPrivKey(walletIndex);
868
907
  accAddress = cosmosClient.AccAddress.fromBech32(signer);
869
908
  return [4 /*yield*/, this.cosmosClient.signAndBroadcast(unsignedStdTx, privateKey, accAddress)];
870
- case 3: return [2 /*return*/, (_c = (_b = (_f.sent())) === null || _b === void 0 ? void 0 : _b.txhash) !== null && _c !== void 0 ? _c : ''];
909
+ case 3: return [2 /*return*/, (_g = (_f = (_k.sent())) === null || _f === void 0 ? void 0 : _f.txhash) !== null && _g !== void 0 ? _g : ''];
871
910
  }
872
911
  });
873
912
  });
@@ -879,22 +918,39 @@ var Client = /** @class */ (function () {
879
918
  * @returns {TxHash} The transaction hash.
880
919
  */
881
920
  Client.prototype.transfer = function (_a) {
882
- var _b = _a.walletIndex, walletIndex = _b === void 0 ? 0 : _b, _c = _a.asset, asset = _c === void 0 ? xchainUtil.AssetRuneNative : _c, amount = _a.amount, recipient = _a.recipient, memo = _a.memo;
921
+ var _b, _c, _d, _e;
922
+ var _f = _a.walletIndex, walletIndex = _f === void 0 ? 0 : _f, _g = _a.asset, asset = _g === void 0 ? xchainUtil.AssetRuneNative : _g, amount = _a.amount, recipient = _a.recipient, memo = _a.memo;
883
923
  return __awaiter(this, void 0, void 0, function () {
884
- var assetBalance, fee, transferResult;
885
- return __generator(this, function (_d) {
886
- switch (_d.label) {
924
+ var balances, runeBalance, assetBalance, fee, transferResult;
925
+ return __generator(this, function (_h) {
926
+ switch (_h.label) {
887
927
  case 0:
888
928
  registerCodecs(getPrefix(this.network));
889
- return [4 /*yield*/, this.getBalance(this.getAddress(walletIndex), [asset])];
929
+ return [4 /*yield*/, this.getBalance(this.getAddress(walletIndex))];
890
930
  case 1:
891
- assetBalance = _d.sent();
931
+ balances = _h.sent();
932
+ runeBalance = (_c = (_b = balances.filter(function (_a) {
933
+ var asset = _a.asset;
934
+ return isAssetRuneNative(asset);
935
+ })[0]) === null || _b === void 0 ? void 0 : _b.amount) !== null && _c !== void 0 ? _c : xchainUtil.baseAmount(0, DECIMAL);
936
+ assetBalance = (_e = (_d = balances.filter(function (_a) {
937
+ var assetInList = _a.asset;
938
+ return xchainUtil.assetToString(assetInList) === xchainUtil.assetToString(asset);
939
+ })[0]) === null || _d === void 0 ? void 0 : _d.amount) !== null && _e !== void 0 ? _e : xchainUtil.baseAmount(0, DECIMAL);
892
940
  return [4 /*yield*/, this.getFees()];
893
941
  case 2:
894
- fee = _d.sent();
895
- if (assetBalance.length === 0 ||
896
- assetBalance[0].amount.amount().lt(amount.amount().plus(fee[xchainClient.FeeOption.Average].amount()))) {
897
- throw new Error('insufficient funds');
942
+ fee = (_h.sent()).average;
943
+ if (isAssetRuneNative(asset)) {
944
+ // amount + fee < runeBalance
945
+ if (runeBalance.lt(amount.plus(fee))) {
946
+ throw new Error('insufficient funds');
947
+ }
948
+ }
949
+ else {
950
+ // amount < assetBalances && runeBalance < fee
951
+ if (assetBalance.lt(amount) || runeBalance.lt(fee)) {
952
+ throw new Error('insufficient funds');
953
+ }
898
954
  }
899
955
  return [4 /*yield*/, this.cosmosClient.transfer({
900
956
  privkey: this.getPrivKey(walletIndex),
@@ -909,7 +965,7 @@ var Client = /** @class */ (function () {
909
965
  },
910
966
  })];
911
967
  case 3:
912
- transferResult = _d.sent();
968
+ transferResult = _h.sent();
913
969
  if (!isBroadcastSuccess(transferResult)) {
914
970
  throw new Error("failed to broadcast transaction: " + transferResult.txhash);
915
971
  }
@@ -925,7 +981,7 @@ var Client = /** @class */ (function () {
925
981
  * @returns {StdTx} The signed transaction.
926
982
  */
927
983
  Client.prototype.transferOffline = function (_a) {
928
- var _b = _a.walletIndex, walletIndex = _b === void 0 ? 0 : _b, _c = _a.asset, asset = _c === void 0 ? xchainUtil.AssetRuneNative : _c, amount = _a.amount, recipient = _a.recipient, memo = _a.memo, _d = _a.from_balance, from_balance = _d === void 0 ? xchainUtil.baseAmount('0', DECIMAL) : _d, _e = _a.from_account_number, from_account_number = _e === void 0 ? '0' : _e, _f = _a.from_sequence, from_sequence = _f === void 0 ? '0' : _f;
984
+ var _b = _a.walletIndex, walletIndex = _b === void 0 ? 0 : _b, _c = _a.asset, asset = _c === void 0 ? xchainUtil.AssetRuneNative : _c, amount = _a.amount, recipient = _a.recipient, memo = _a.memo, from_rune_balance = _a.from_rune_balance, _d = _a.from_asset_balance, from_asset_balance = _d === void 0 ? xchainUtil.baseAmount(0, DECIMAL) : _d, _e = _a.from_account_number, from_account_number = _e === void 0 ? '0' : _e, _f = _a.from_sequence, from_sequence = _f === void 0 ? '0' : _f;
929
985
  return __awaiter(this, void 0, void 0, function () {
930
986
  var fee, result;
931
987
  return __generator(this, function (_g) {
@@ -934,10 +990,18 @@ var Client = /** @class */ (function () {
934
990
  registerCodecs(getPrefix(this.network));
935
991
  return [4 /*yield*/, this.getFees()];
936
992
  case 1:
937
- fee = _g.sent();
938
- if (from_balance === xchainUtil.baseAmount('0', DECIMAL) ||
939
- from_balance.amount().lt(amount.amount().plus(fee[xchainClient.FeeOption.Average].amount()))) {
940
- throw new Error('insufficient funds');
993
+ fee = (_g.sent()).average;
994
+ if (isAssetRuneNative(asset)) {
995
+ // amount + fee < runeBalance
996
+ if (from_rune_balance.lt(amount.plus(fee))) {
997
+ throw new Error('insufficient funds');
998
+ }
999
+ }
1000
+ else {
1001
+ // amount < assetBalances && runeBalance < fee
1002
+ if (from_asset_balance.lt(amount) || from_rune_balance.lt(fee)) {
1003
+ throw new Error('insufficient funds');
1004
+ }
941
1005
  }
942
1006
  return [4 /*yield*/, this.cosmosClient.transferSignedOffline({
943
1007
  privkey: this.getPrivKey(walletIndex),
@@ -981,21 +1045,20 @@ exports.DEFAULT_GAS_VALUE = DEFAULT_GAS_VALUE;
981
1045
  exports.DEPOSIT_GAS_VALUE = DEPOSIT_GAS_VALUE;
982
1046
  exports.MAX_TX_COUNT = MAX_TX_COUNT;
983
1047
  exports.MsgNativeTx = MsgNativeTx;
1048
+ exports.assetFromDenom = assetFromDenom;
984
1049
  exports.buildDepositTx = buildDepositTx;
985
- exports.getAsset = getAsset;
986
1050
  exports.getBalance = getBalance;
987
- exports.getChainId = getChainId;
988
1051
  exports.getDefaultClientUrl = getDefaultClientUrl;
989
1052
  exports.getDefaultExplorerUrls = getDefaultExplorerUrls;
990
1053
  exports.getDefaultFees = getDefaultFees;
991
1054
  exports.getDenom = getDenom;
992
- exports.getDenomWithChain = getDenomWithChain;
993
1055
  exports.getDepositTxDataFromLogs = getDepositTxDataFromLogs;
994
1056
  exports.getExplorerAddressUrl = getExplorerAddressUrl;
995
1057
  exports.getExplorerTxUrl = getExplorerTxUrl;
996
1058
  exports.getExplorerUrl = getExplorerUrl;
997
1059
  exports.getPrefix = getPrefix;
998
1060
  exports.getTxType = getTxType;
1061
+ exports.isAssetRuneNative = isAssetRuneNative;
999
1062
  exports.isBroadcastSuccess = isBroadcastSuccess;
1000
1063
  exports.isMsgMultiSend = isMsgMultiSend;
1001
1064
  exports.isMsgSend = isMsgSend;
@@ -1,4 +1,4 @@
1
- import { Network, Tx } from '@xchainjs/xchain-client';
1
+ import { Network, Tx, TxParams } from '@xchainjs/xchain-client';
2
2
  import { Asset, BaseAmount } from '@xchainjs/xchain-util';
3
3
  export declare type NodeUrl = {
4
4
  node: string;
@@ -11,9 +11,12 @@ export declare type ExplorerUrls = {
11
11
  address: ExplorerUrl;
12
12
  };
13
13
  export declare type ExplorerUrl = Record<Network, string>;
14
+ export declare type ChainId = string;
15
+ export declare type ChainIds = Record<Network, ChainId>;
14
16
  export declare type ThorchainClientParams = {
15
17
  clientUrl?: ClientUrl;
16
18
  explorerUrls?: ExplorerUrls;
19
+ chainIds?: ChainIds;
17
20
  };
18
21
  export declare type DepositParam = {
19
22
  walletIndex?: number;
@@ -22,3 +25,16 @@ export declare type DepositParam = {
22
25
  memo: string;
23
26
  };
24
27
  export declare type TxData = Pick<Tx, 'from' | 'to' | 'type'>;
28
+ export declare type TxOfflineParams = TxParams & {
29
+ /**
30
+ * Balance of Rune to send from
31
+ */
32
+ from_rune_balance: BaseAmount;
33
+ /**
34
+ * Balance of asset to send from
35
+ * Optional: It can be ignored if asset to send from is RUNE
36
+ */
37
+ from_asset_balance?: BaseAmount;
38
+ from_account_number: string;
39
+ from_sequence: string;
40
+ };
package/lib/util.d.ts CHANGED
@@ -4,33 +4,33 @@ import { Asset } from '@xchainjs/xchain-util';
4
4
  import { Msg } from 'cosmos-client';
5
5
  import { StdTx } from 'cosmos-client/x/auth';
6
6
  import { MsgMultiSend, MsgSend } from 'cosmos-client/x/bank';
7
- import { ClientUrl, ExplorerUrls, TxData } from './types';
7
+ import { ChainId, ClientUrl, ExplorerUrls, TxData } from './types';
8
8
  import { MsgNativeTx } from './types/messages';
9
9
  export declare const DECIMAL = 8;
10
10
  export declare const DEFAULT_GAS_VALUE = "2000000";
11
11
  export declare const DEPOSIT_GAS_VALUE = "500000000";
12
12
  export declare const MAX_TX_COUNT = 100;
13
13
  /**
14
- * Get denomination from Asset
14
+ * Checks whether an asset is `AssetRuneNative`
15
15
  *
16
16
  * @param {Asset} asset
17
- * @returns {string} The denomination of the given asset.
17
+ * @returns {boolean} `true` or `false`
18
18
  */
19
- export declare const getDenom: (asset: Asset) => string;
19
+ export declare const isAssetRuneNative: (asset: Asset) => boolean;
20
20
  /**
21
- * Get denomination with chainname from Asset
21
+ * Get denomination from Asset
22
22
  *
23
23
  * @param {Asset} asset
24
- * @returns {string} The denomination with chainname of the given asset.
24
+ * @returns {string} The denomination of the given asset.
25
25
  */
26
- export declare const getDenomWithChain: (asset: Asset) => string;
26
+ export declare const getDenom: (asset: Asset) => string;
27
27
  /**
28
28
  * Get Asset from denomination
29
29
  *
30
30
  * @param {string} denom
31
31
  * @returns {Asset|null} The asset of the given denomination.
32
32
  */
33
- export declare const getAsset: (denom: string) => Asset | null;
33
+ export declare const assetFromDenom: (denom: string) => Asset | null;
34
34
  /**
35
35
  * Type guard for MsgSend
36
36
  *
@@ -60,14 +60,6 @@ export declare const isBroadcastSuccess: (response: unknown) => boolean;
60
60
  *
61
61
  **/
62
62
  export declare const getPrefix: (network: Network) => "thor" | "sthor" | "tthor";
63
- /**
64
- * Get the chain id.
65
- *
66
- * @param {Network} network
67
- * @returns {string} The chain id based on the network.
68
- *
69
- */
70
- export declare const getChainId: (network: Network) => "thorchain" | "thorchain-stagenet";
71
63
  /**
72
64
  * Register Codecs based on the prefix.
73
65
  *
@@ -99,12 +91,19 @@ export declare const getTxType: (txData: string, encoding: 'base64' | 'hex') =>
99
91
  /**
100
92
  * Structure StdTx from MsgNativeTx.
101
93
  *
102
- * @param {string} txId The transaction id.
94
+ * @param {MsgNativeTx} msgNativeTx Msg of type `MsgNativeTx`.
95
+ * @param {string} nodeUrl Node url
96
+ * @param {chainId} ChainId Chain id of the network
97
+ *
103
98
  * @returns {Tx} The transaction details of the given transaction id.
104
99
  *
105
100
  * @throws {"Invalid client url"} Thrown if the client url is an invalid one.
106
101
  */
107
- export declare const buildDepositTx: (msgNativeTx: MsgNativeTx, nodeUrl: string) => Promise<StdTx>;
102
+ export declare const buildDepositTx: ({ msgNativeTx, nodeUrl, chainId, }: {
103
+ msgNativeTx: MsgNativeTx;
104
+ nodeUrl: string;
105
+ chainId: ChainId;
106
+ }) => Promise<StdTx>;
108
107
  /**
109
108
  * Get the balance of a given address.
110
109
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xchainjs/xchain-thorchain",
3
- "version": "0.20.1",
3
+ "version": "0.22.0",
4
4
  "description": "Custom Thorchain client and utilities used by XChainJS clients",
5
5
  "keywords": [
6
6
  "THORChain",
@@ -33,11 +33,11 @@
33
33
  },
34
34
  "devDependencies": {
35
35
  "@types/big.js": "^6.0.0",
36
- "@xchainjs/xchain-client": "^0.11.0",
37
- "@xchainjs/xchain-cosmos": "^0.15.0",
36
+ "@xchainjs/xchain-client": "^0.11.1",
37
+ "@xchainjs/xchain-cosmos": "^0.16.1",
38
38
  "@xchainjs/xchain-crypto": "^0.2.4",
39
- "@xchainjs/xchain-util": "^0.3.0",
40
- "axios": "^0.21.0",
39
+ "@xchainjs/xchain-util": "^0.5.1",
40
+ "axios": "^0.25.0",
41
41
  "cosmos-client": "0.39.2",
42
42
  "nock": "^13.0.5"
43
43
  },
@@ -45,11 +45,11 @@
45
45
  "access": "public"
46
46
  },
47
47
  "peerDependencies": {
48
- "@xchainjs/xchain-client": "^0.11.0",
49
- "@xchainjs/xchain-cosmos": "^0.15.0",
48
+ "@xchainjs/xchain-client": "^0.11.1",
49
+ "@xchainjs/xchain-cosmos": "^0.16.1",
50
50
  "@xchainjs/xchain-crypto": "^0.2.4",
51
- "@xchainjs/xchain-util": "^0.3.0",
52
- "axios": "^0.21.0",
51
+ "@xchainjs/xchain-util": "^0.5.1",
52
+ "axios": "^0.25.0",
53
53
  "cosmos-client": "0.39.2"
54
54
  }
55
- }
55
+ }