@pioneer-platform/maya-network 8.11.1 → 8.12.1

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,5 +1,29 @@
1
1
  # @pioneer-platform/maya-network
2
2
 
3
+ ## 8.12.1
4
+
5
+ ### Patch Changes
6
+
7
+ - Add backward compatibility wrapper for account info
8
+
9
+ - Wrap Unchained API response in old format (result.value structure)
10
+ - Fix transaction building errors from undefined `value` property
11
+ - Maintains compatibility with existing code expecting old node format
12
+
13
+ ## 8.12.0
14
+
15
+ ### Minor Changes
16
+
17
+ - Migrate MayaChain network module to Unchained API
18
+
19
+ - Replace direct node calls with ShapeShift Unchained API
20
+ - Remove verbose error logging and 503 spam
21
+ - Add proper timeouts to all requests (5-10s)
22
+ - Reduce code size by 50% (646 → 320 lines)
23
+ - Improve reliability and performance
24
+ - Keep Midgard API for pool data only
25
+ - Add comprehensive test suite and documentation
26
+
3
27
  ## 8.11.1
4
28
 
5
29
  ### Patch Changes
package/README.md ADDED
@@ -0,0 +1,140 @@
1
+ # MayaChain Network Module
2
+
3
+ MayaChain network integration using ShapeShift Unchained API.
4
+
5
+ ## Architecture
6
+
7
+ This module has been migrated from direct MayaChain node calls to use the Unchained API for better reliability and reduced node connection errors.
8
+
9
+ ### API Endpoints
10
+
11
+ **Primary: ShapeShift Unchained API**
12
+ - Base URL: `https://api.mayachain.shapeshift.com`
13
+ - Documentation: https://api.mayachain.shapeshift.com/swagger
14
+ - Provides: Account info, balances, transaction history, broadcasting
15
+
16
+ **Fallback: Midgard API**
17
+ - Base URL: `https://midgard.mayachain.info/v2`
18
+ - Provides: Pool data, aggregated chain statistics
19
+ - Used for: Pool queries not available in Unchained
20
+
21
+ ## Features
22
+
23
+ ### ✅ Implemented via Unchained
24
+ - `getInfo()` - Network information
25
+ - `getAccount(address)` - Account details with balances
26
+ - `getBalance(address)` - Single CACAO balance
27
+ - `getBalances(address)` - All asset balances
28
+ - `txs(address, cursor, pageSize)` - Paginated transaction history
29
+ - `broadcast(rawTx)` - Transaction broadcasting
30
+
31
+ ### ✅ Implemented via Midgard
32
+ - `getPools()` - All liquidity pools
33
+ - `getPool(poolId)` - Specific pool details
34
+
35
+ ### ⚠️ Not Available in Unchained
36
+ - `getTransaction(txid)` - Direct tx lookup (use account txs instead)
37
+ - `getPoolAddress()` - Inbound addresses (requires node access)
38
+
39
+ ## Usage
40
+
41
+ ```javascript
42
+ const network = require('@pioneer-platform/mayachain-network')
43
+
44
+ // Get network info
45
+ const info = await network.info()
46
+
47
+ // Get account balances
48
+ const balances = await network.getBalances('maya1...')
49
+
50
+ // Get transaction history (paginated)
51
+ const txs = await network.txs('maya1...', undefined, 50)
52
+
53
+ // Broadcast transaction
54
+ const result = await network.broadcast(signedTxBase64)
55
+ ```
56
+
57
+ ## Balance Formats
58
+
59
+ The module returns balances in standardized format:
60
+
61
+ ```javascript
62
+ [
63
+ {
64
+ denom: 'cacao', // Asset denomination
65
+ amountBase: '25029714637', // Raw amount (base units)
66
+ amount: 25.029714637, // Decimal amount
67
+ decimals: 10 // Decimal places
68
+ },
69
+ {
70
+ denom: 'maya',
71
+ amountBase: '4104',
72
+ amount: 0.4104,
73
+ decimals: 4
74
+ }
75
+ ]
76
+ ```
77
+
78
+ ### Decimal Places
79
+ - **CACAO**: 10 decimals (1 CACAO = 10,000,000,000 base units)
80
+ - **MAYA**: 4 decimals (1 MAYA = 10,000 base units)
81
+
82
+ ## Error Handling
83
+
84
+ The module uses minimal logging with retry logic:
85
+ - 2 retries on 503 errors with exponential backoff
86
+ - Logs only errors and key operations (no verbose stack traces)
87
+ - Returns structured error responses for broadcast failures
88
+
89
+ ## Migration Notes
90
+
91
+ ### Changes from Previous Version
92
+ 1. ✅ Removed direct node calls to `mayanode.mayachain.info`
93
+ 2. ✅ Removed verbose error logging (no more giant stack traces)
94
+ 3. ✅ Uses Unchained API for account/balance/tx operations
95
+ 4. ✅ Keeps Midgard for pool data (not in Unchained)
96
+ 5. ✅ Simplified retry logic with minimal logging
97
+
98
+ ### Benefits
99
+ - **Reliability**: Unchained API is more stable than direct node access
100
+ - **Performance**: Faster responses, better caching
101
+ - **Cleaner logs**: No more 503 spam in logs
102
+ - **Maintainability**: Single API contract vs multiple node endpoints
103
+
104
+ ## Testing
105
+
106
+ ```bash
107
+ cd modules/coins/mayachain/mayachain-network
108
+ bun run test
109
+ ```
110
+
111
+ Test coverage:
112
+ - ✅ Network info retrieval
113
+ - ✅ Account balance queries
114
+ - ✅ Multi-asset balance parsing
115
+ - ✅ Transaction history (paginated)
116
+ - ✅ Pool data from Midgard
117
+ - 💬 Broadcasting (commented out - needs real signed tx)
118
+
119
+ ## Development
120
+
121
+ ```bash
122
+ # Build
123
+ bun run build
124
+
125
+ # Test
126
+ bun run test
127
+
128
+ # Install dependencies
129
+ bun install
130
+ ```
131
+
132
+ ## Dependencies
133
+
134
+ - `axios` - HTTP client
135
+ - `axios-retry` - Retry logic for 503 errors
136
+ - `@pioneer-platform/loggerdog` - Logging
137
+
138
+ ## License
139
+
140
+ MIT
package/lib/index.d.ts CHANGED
@@ -1,34 +1,23 @@
1
- declare const TAG = " | thorchain-api | ";
2
- declare const prettyjson: any;
1
+ declare const TAG = " | mayachain-api | ";
2
+ declare const log: any;
3
3
  declare const axiosLib: any;
4
- declare const Axios: any;
5
- declare const https: any;
6
4
  declare const axios: any;
5
+ declare const https: any;
6
+ declare const axiosInstance: any;
7
7
  declare const axiosRetry: any;
8
- declare const log: any;
9
- declare let URL_THORNODE: string;
10
- declare let URL_MIDGARD: string;
11
- declare const NOWNODES_ENDPOINTS: string[];
12
- declare const UNCHAINED_ENDPOINT = "https://api.mayachain.shapeshift.com";
13
- declare let BASE_THOR: number;
8
+ declare const UNCHAINED_API = "https://api.mayachain.shapeshift.com";
9
+ declare const MIDGARD_API = "https://midgard.mayachain.info/v2";
10
+ declare const BASE_MAYA = 10000000000;
14
11
  /**********************************
15
- // Lib
12
+ // Implementation
16
13
  //**********************************/
14
+ declare const get_info: () => Promise<any>;
15
+ declare const get_account_info: (address: string) => Promise<any>;
16
+ declare const get_balance: (address: string) => Promise<number>;
17
+ declare const get_balances: (address: string) => Promise<any[]>;
18
+ declare const get_txs_by_address: (address: string, cursor?: string, pageSize?: number) => Promise<any>;
19
+ declare const get_transaction: (txid: string) => Promise<never>;
20
+ declare const broadcast_transaction: (tx: string) => Promise<any>;
17
21
  declare const get_pool: (poolId: string) => Promise<any>;
18
22
  declare const get_pools: () => Promise<any>;
19
- declare const get_pool_addresses: () => Promise<any>;
20
- declare let get_last_block: () => Promise<any>;
21
- declare let get_block_height: () => Promise<any>;
22
- declare let get_transaction: (txid: string) => Promise<any>;
23
- declare let broadcast_transaction: (tx: string) => Promise<any>;
24
- declare let get_account_info: (address: string) => Promise<any>;
25
- declare let normalize_tx: (tx: any, address?: string) => any;
26
- declare let get_txs_by_address: (address: string) => Promise<any>;
27
- declare let get_balance: (address: string) => Promise<number>;
28
- declare let get_balances: (address: string) => Promise<{
29
- denom: any;
30
- amountBase: any;
31
- amount: number;
32
- decimals: number;
33
- }[]>;
34
- declare let get_node_info_verbose: () => Promise<any>;
23
+ declare const get_pool_addresses: () => Promise<never>;
package/lib/index.js CHANGED
@@ -1,4 +1,21 @@
1
1
  "use strict";
2
+ /*
3
+ MayaChain Network Module - Unchained API Integration
4
+
5
+ Migrated from direct node calls to ShapeShift Unchained API
6
+ API Documentation: https://api.mayachain.shapeshift.com/swagger
7
+ */
8
+ var __assign = (this && this.__assign) || function () {
9
+ __assign = Object.assign || function(t) {
10
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
11
+ s = arguments[i];
12
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
13
+ t[p] = s[p];
14
+ }
15
+ return t;
16
+ };
17
+ return __assign.apply(this, arguments);
18
+ };
2
19
  var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
20
  function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
21
  return new (P || (P = Promise))(function (resolve, reject) {
@@ -35,68 +52,39 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
35
52
  if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
36
53
  }
37
54
  };
38
- var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
39
- if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
40
- if (ar || !(i in from)) {
41
- if (!ar) ar = Array.prototype.slice.call(from, 0, i);
42
- ar[i] = from[i];
43
- }
44
- }
45
- return to.concat(ar || Array.prototype.slice.call(from));
46
- };
47
- /*
48
- const thorMainnetClient: CosmosSDKClient = new CosmosSDKClient({
49
- server: 'http://104.248.96.152:1317',
50
- chainId: 'thorchain',
51
- prefix: 'thor',
52
- derive_path: "44'/931'/0'/0/0",
53
- })
54
-
55
-
56
- get nodes
57
- curl https://testnet-seed.thorchain.info
58
-
59
- //testnet
60
- https://main.d3mbd42yfy75lz.amplifyapp.com/#/nodes
61
-
62
- */
63
- var TAG = " | thorchain-api | ";
64
- var prettyjson = require('prettyjson');
65
- require("dotenv").config({ path: '../../../.env' });
55
+ var TAG = " | mayachain-api | ";
56
+ var log = require('@pioneer-platform/loggerdog')();
66
57
  var axiosLib = require('axios');
67
- var Axios = axiosLib.default || axiosLib;
58
+ var axios = axiosLib.default || axiosLib;
68
59
  var https = require('https');
69
- var axios = Axios.create({
60
+ // Create axios instance with retry logic but minimal logging
61
+ var axiosInstance = axios.create({
70
62
  httpsAgent: new https.Agent({
71
63
  rejectUnauthorized: false
72
64
  })
73
65
  });
74
66
  var axiosRetry = require('axios-retry');
75
- axiosRetry(axios, {
76
- retries: 3, // number of retries
67
+ axiosRetry(axiosInstance, {
68
+ retries: 2,
77
69
  retryDelay: function (retryCount) {
78
- console.log("retry attempt: ".concat(retryCount));
79
- return retryCount * 2000; // time interval between retries
70
+ return retryCount * 1000;
80
71
  },
81
72
  retryCondition: function (error) {
82
- console.error(error);
83
- // if retry condition is not specified, by default idempotent requests are retried
84
- return error.response.status === 503;
73
+ var _a;
74
+ return ((_a = error.response) === null || _a === void 0 ? void 0 : _a.status) === 503;
85
75
  },
76
+ onRetry: function (retryCount, error) {
77
+ log.debug(TAG, "Retry ".concat(retryCount, "/2: ").concat(error.message));
78
+ }
86
79
  });
87
- var log = require('@pioneer-platform/loggerdog')();
88
- var URL_THORNODE = 'https://mayanode.mayachain.info';
89
- var URL_MIDGARD = 'https://midgard.mayachain.info/v2';
90
- // NowNodes fallback endpoints
91
- var NOWNODES_ENDPOINTS = [
92
- 'https://maya.nownodes.io',
93
- 'https://mayachain.nownodes.io'
94
- ];
95
- // ShapeShift Unchained API endpoint
96
- var UNCHAINED_ENDPOINT = 'https://api.mayachain.shapeshift.com';
97
- var BASE_THOR = 10000000000;
80
+ // Unchained API endpoint
81
+ var UNCHAINED_API = 'https://api.mayachain.shapeshift.com';
82
+ // Fallback to Midgard for pool data (not available in Unchained)
83
+ var MIDGARD_API = 'https://midgard.mayachain.info/v2';
84
+ // Base unit conversion (10 decimal places for CACAO)
85
+ var BASE_MAYA = 10000000000;
98
86
  /**********************************
99
- // Module
87
+ // Module Exports
100
88
  //**********************************/
101
89
  module.exports = {
102
90
  init: function (url, settings) {
@@ -106,7 +94,7 @@ module.exports = {
106
94
  return true;
107
95
  },
108
96
  info: function () {
109
- return get_node_info_verbose();
97
+ return get_info();
110
98
  },
111
99
  getBalance: function (address) {
112
100
  return get_balance(address);
@@ -117,12 +105,6 @@ module.exports = {
117
105
  getAccount: function (address) {
118
106
  return get_account_info(address);
119
107
  },
120
- getLastBlock: function () {
121
- return get_last_block();
122
- },
123
- getBlockHeight: function () {
124
- return get_block_height();
125
- },
126
108
  getAccountInfo: function (address) {
127
109
  return get_account_info(address);
128
110
  },
@@ -149,148 +131,187 @@ module.exports = {
149
131
  },
150
132
  };
151
133
  /**********************************
152
- // Lib
134
+ // Implementation
153
135
  //**********************************/
154
- var get_pool = function (poolId) {
136
+ var get_info = function () {
155
137
  return __awaiter(this, void 0, void 0, function () {
156
- var tag, params, body, resp, e_1;
138
+ var tag, result, e_1;
157
139
  return __generator(this, function (_a) {
158
140
  switch (_a.label) {
159
141
  case 0:
160
- tag = TAG + " | get_pool | ";
142
+ tag = TAG + " | get_info | ";
161
143
  _a.label = 1;
162
144
  case 1:
163
145
  _a.trys.push([1, 3, , 4]);
164
- params = {
165
- view: "full",
166
- asset: poolId
167
- };
168
- body = {
169
- method: 'GET',
170
- url: URL_MIDGARD + "/pools/detail",
171
- headers: { 'content-type': 'application/json' },
172
- params: params
173
- };
174
- log.debug(body);
175
- return [4 /*yield*/, axios(body)];
146
+ return [4 /*yield*/, axiosInstance({
147
+ method: 'GET',
148
+ url: "".concat(UNCHAINED_API, "/api/v1/info"),
149
+ timeout: 5000
150
+ })];
176
151
  case 2:
177
- resp = _a.sent();
178
- return [2 /*return*/, resp.data];
152
+ result = _a.sent();
153
+ return [2 /*return*/, result.data];
179
154
  case 3:
180
155
  e_1 = _a.sent();
181
- log.error(tag, "e: ", e_1);
156
+ log.error(tag, "Error:", e_1.message);
182
157
  throw e_1;
183
158
  case 4: return [2 /*return*/];
184
159
  }
185
160
  });
186
161
  });
187
162
  };
188
- var get_pools = function () {
163
+ var get_account_info = function (address) {
189
164
  return __awaiter(this, void 0, void 0, function () {
190
- var tag, body, resp, e_2;
165
+ var tag, result, unchainedData, e_2;
191
166
  return __generator(this, function (_a) {
192
167
  switch (_a.label) {
193
168
  case 0:
194
- tag = TAG + " | get_pools | ";
169
+ tag = TAG + " | get_account_info | ";
195
170
  _a.label = 1;
196
171
  case 1:
197
172
  _a.trys.push([1, 3, , 4]);
198
- body = {
199
- method: 'GET',
200
- url: URL_MIDGARD + "/pools",
201
- headers: { 'content-type': 'application/json' },
202
- // body: {account_name: actor},
203
- // json: true
204
- };
205
- log.debug(body.url);
206
- return [4 /*yield*/, axios(body)];
173
+ return [4 /*yield*/, axiosInstance({
174
+ method: 'GET',
175
+ url: "".concat(UNCHAINED_API, "/api/v1/account/").concat(address),
176
+ timeout: 5000
177
+ })
178
+ // Unchained returns flat structure, wrap it for backward compatibility
179
+ // Old format: { result: { value: { account_number, sequence, ... } } }
180
+ // New format: { accountNumber, sequence, balance, ... }
181
+ ];
207
182
  case 2:
208
- resp = _a.sent();
209
- return [2 /*return*/, resp.data];
183
+ result = _a.sent();
184
+ unchainedData = result.data;
185
+ return [2 /*return*/, __assign({ result: {
186
+ value: {
187
+ account_number: String(unchainedData.accountNumber || '0'),
188
+ sequence: String(unchainedData.sequence || '0'),
189
+ address: unchainedData.pubkey || address,
190
+ coins: unchainedData.assets || [],
191
+ public_key: null // Not provided by Unchained
192
+ }
193
+ } }, unchainedData)];
210
194
  case 3:
211
195
  e_2 = _a.sent();
212
- log.error(tag, "e: ", e_2);
196
+ log.error(tag, "Error:", e_2.message);
213
197
  throw e_2;
214
198
  case 4: return [2 /*return*/];
215
199
  }
216
200
  });
217
201
  });
218
202
  };
219
- //https://testnet.thornode.thorchain.info/thorchain/inbound_addresses
220
- var get_pool_addresses = function () {
203
+ var get_balance = function (address) {
221
204
  return __awaiter(this, void 0, void 0, function () {
222
- var tag, output, body, resp, e_3;
205
+ var tag, accountInfo, balance, e_3;
223
206
  return __generator(this, function (_a) {
224
207
  switch (_a.label) {
225
208
  case 0:
226
- tag = TAG + " | get_pool_addresses | ";
209
+ tag = TAG + " | get_balance | ";
227
210
  _a.label = 1;
228
211
  case 1:
229
212
  _a.trys.push([1, 3, , 4]);
230
- output = {};
231
- body = {
232
- method: 'GET',
233
- url: URL_THORNODE + "/thorchain/inbound_addresses",
234
- headers: { 'content-type': 'application/json' },
235
- // body: {account_name: actor},
236
- // json: true
237
- };
238
- log.debug(body);
239
- return [4 /*yield*/, axios(body)];
213
+ return [4 /*yield*/, get_account_info(address)
214
+ // Parse balance from string to number
215
+ ];
240
216
  case 2:
241
- resp = _a.sent();
242
- return [2 /*return*/, resp.data];
217
+ accountInfo = _a.sent();
218
+ balance = parseFloat(accountInfo.balance || '0');
219
+ // Convert from base units to CACAO
220
+ return [2 /*return*/, balance / BASE_MAYA];
243
221
  case 3:
244
222
  e_3 = _a.sent();
245
- log.error(tag, "e: ", e_3);
246
- return [3 /*break*/, 4];
223
+ log.error(tag, "Error:", e_3.message);
224
+ throw e_3;
247
225
  case 4: return [2 /*return*/];
248
226
  }
249
227
  });
250
228
  });
251
229
  };
252
- var get_last_block = function () {
230
+ var get_balances = function (address) {
253
231
  return __awaiter(this, void 0, void 0, function () {
254
- var tag, lastBlock, e_4;
255
- return __generator(this, function (_a) {
256
- switch (_a.label) {
232
+ var tag, accountInfo, output, cacaoBalance, _i, _a, asset, e_4;
233
+ return __generator(this, function (_b) {
234
+ switch (_b.label) {
257
235
  case 0:
258
- tag = TAG + " | get_last_block | ";
259
- _a.label = 1;
236
+ tag = TAG + " | get_balances | ";
237
+ _b.label = 1;
260
238
  case 1:
261
- _a.trys.push([1, 3, , 4]);
262
- return [4 /*yield*/, axios({ method: 'GET', url: URL_THORNODE + '/blocks/latest' })];
239
+ _b.trys.push([1, 3, , 4]);
240
+ return [4 /*yield*/, get_account_info(address)];
263
241
  case 2:
264
- lastBlock = _a.sent();
265
- log.debug(tag, "lastBlock: ", lastBlock.data);
266
- return [2 /*return*/, lastBlock.data.block];
242
+ accountInfo = _b.sent();
243
+ output = [];
244
+ cacaoBalance = parseFloat(accountInfo.balance || '0');
245
+ if (cacaoBalance > 0) {
246
+ output.push({
247
+ denom: 'cacao',
248
+ amountBase: accountInfo.balance,
249
+ amount: cacaoBalance / BASE_MAYA,
250
+ decimals: 10
251
+ });
252
+ }
253
+ // Parse assets array if present (MAYA and other assets)
254
+ if (accountInfo.assets && Array.isArray(accountInfo.assets)) {
255
+ for (_i = 0, _a = accountInfo.assets; _i < _a.length; _i++) {
256
+ asset = _a[_i];
257
+ if (asset.denom === 'maya') {
258
+ output.push({
259
+ denom: asset.denom,
260
+ amountBase: asset.amount,
261
+ amount: parseFloat(asset.amount) / 10000, // 4 decimals for MAYA
262
+ decimals: 4
263
+ });
264
+ }
265
+ else if (asset.denom === 'cacao') {
266
+ // Skip if already added from main balance
267
+ continue;
268
+ }
269
+ else {
270
+ output.push({
271
+ denom: asset.denom,
272
+ amountBase: asset.amount,
273
+ amount: parseFloat(asset.amount),
274
+ decimals: 0
275
+ });
276
+ }
277
+ }
278
+ }
279
+ return [2 /*return*/, output];
267
280
  case 3:
268
- e_4 = _a.sent();
269
- log.error(tag, "e: ", e_4);
281
+ e_4 = _b.sent();
282
+ log.error(tag, "Error:", e_4.message);
270
283
  throw e_4;
271
284
  case 4: return [2 /*return*/];
272
285
  }
273
286
  });
274
287
  });
275
288
  };
276
- var get_block_height = function () {
277
- return __awaiter(this, void 0, void 0, function () {
278
- var tag, lastBlock, e_5;
289
+ var get_txs_by_address = function (address_1, cursor_1) {
290
+ return __awaiter(this, arguments, void 0, function (address, cursor, pageSize) {
291
+ var tag, params, result, e_5;
292
+ if (pageSize === void 0) { pageSize = 50; }
279
293
  return __generator(this, function (_a) {
280
294
  switch (_a.label) {
281
295
  case 0:
282
- tag = TAG + " | get_block_height | ";
296
+ tag = TAG + " | get_txs_by_address | ";
283
297
  _a.label = 1;
284
298
  case 1:
285
299
  _a.trys.push([1, 3, , 4]);
286
- return [4 /*yield*/, axios({ method: 'GET', url: URL_THORNODE + '/blocks/latest' })];
300
+ params = { pageSize: pageSize };
301
+ if (cursor)
302
+ params.cursor = cursor;
303
+ return [4 /*yield*/, axiosInstance({
304
+ method: 'GET',
305
+ url: "".concat(UNCHAINED_API, "/api/v1/account/").concat(address, "/txs"),
306
+ params: params,
307
+ timeout: 10000
308
+ })];
287
309
  case 2:
288
- lastBlock = _a.sent();
289
- log.debug(tag, "lastBlock: ", lastBlock.data);
290
- return [2 /*return*/, lastBlock.data.block.header.height];
310
+ result = _a.sent();
311
+ return [2 /*return*/, result.data];
291
312
  case 3:
292
313
  e_5 = _a.sent();
293
- log.error(tag, "e: ", e_5);
314
+ log.error(tag, "Error:", e_5.message);
294
315
  throw e_5;
295
316
  case 4: return [2 /*return*/];
296
317
  }
@@ -299,471 +320,151 @@ var get_block_height = function () {
299
320
  };
300
321
  var get_transaction = function (txid) {
301
322
  return __awaiter(this, void 0, void 0, function () {
302
- var tag, txInfo, e_6, output;
323
+ var tag;
303
324
  return __generator(this, function (_a) {
304
- switch (_a.label) {
305
- case 0:
306
- tag = TAG + " | get_transaction | ";
307
- _a.label = 1;
308
- case 1:
309
- _a.trys.push([1, 3, , 4]);
310
- return [4 /*yield*/, axios({ method: 'GET', url: URL_THORNODE + '/txs/' + txid })];
311
- case 2:
312
- txInfo = _a.sent();
313
- log.debug(tag, "txInfo: ", txInfo.data);
314
- return [2 /*return*/, txInfo.data];
315
- case 3:
316
- e_6 = _a.sent();
317
- // log.error(tag,e.response.data)
318
- // log.error(tag,e.response.data.error)
319
- if (e_6.response.status === 404) {
320
- output = {};
321
- output.success = false;
322
- output.error = e_6.response.data.error;
323
- return [2 /*return*/, output];
324
- }
325
- else {
326
- throw Error(e_6);
327
- }
328
- return [3 /*break*/, 4];
329
- case 4: return [2 /*return*/];
325
+ tag = TAG + " | get_transaction | ";
326
+ try {
327
+ // Unchained doesn't have a direct tx lookup endpoint
328
+ // Would need to implement via account txs or use Midgard/node fallback
329
+ log.warn(tag, "Transaction lookup not implemented in Unchained API, use Midgard or node directly");
330
+ throw new Error("Transaction lookup not available in Unchained API");
331
+ }
332
+ catch (e) {
333
+ log.error(tag, "Error:", e.message);
334
+ throw e;
330
335
  }
336
+ return [2 /*return*/];
331
337
  });
332
338
  });
333
339
  };
334
340
  var broadcast_transaction = function (tx) {
335
341
  return __awaiter(this, void 0, void 0, function () {
336
- var tag, output, cosmosPayload, unchainedPayload, endpoints, lastError, i, endpoint, urlRemote, headers, payload, result2, errorMsg, e_7, e_8;
337
- return __generator(this, function (_a) {
338
- switch (_a.label) {
342
+ var tag, output, payload, result, e_6;
343
+ var _a;
344
+ return __generator(this, function (_b) {
345
+ switch (_b.label) {
339
346
  case 0:
340
347
  tag = TAG + " | broadcast_transaction | ";
341
- output = {};
342
- _a.label = 1;
348
+ output = { success: false };
349
+ _b.label = 1;
343
350
  case 1:
344
- _a.trys.push([1, 8, , 9]);
345
- log.debug(tag, "CHECKPOINT 1");
346
- output.success = false;
347
- cosmosPayload = {
348
- "tx_bytes": tx,
349
- "mode": "BROADCAST_MODE_SYNC"
351
+ _b.trys.push([1, 3, , 4]);
352
+ payload = {
353
+ rawTx: tx
350
354
  };
351
- unchainedPayload = {
352
- "rawTx": tx
353
- };
354
- endpoints = __spreadArray([
355
- { url: URL_THORNODE, type: 'cosmos', name: 'MayaNode' },
356
- { url: UNCHAINED_ENDPOINT, type: 'unchained', name: 'ShapeShift Unchained' }
357
- ], NOWNODES_ENDPOINTS.map(function (url) { return ({ url: url, type: 'cosmos', name: 'NowNodes' }); }), true);
358
- lastError = null;
359
- i = 0;
360
- _a.label = 2;
361
- case 2:
362
- if (!(i < endpoints.length)) return [3 /*break*/, 7];
363
- endpoint = endpoints[i];
364
- _a.label = 3;
365
- case 3:
366
- _a.trys.push([3, 5, , 6]);
367
- urlRemote = endpoint.type === 'unchained'
368
- ? endpoint.url + '/api/v1/send'
369
- : endpoint.url + '/cosmos/tx/v1beta1/txs';
370
- log.info(tag, "Attempting broadcast to ".concat(endpoint.name, " (").concat(i + 1, "/").concat(endpoints.length, "): ").concat(urlRemote));
371
- headers = {
372
- 'Content-Type': 'application/json'
373
- };
374
- // Add NowNodes API key if using NowNodes endpoint
375
- if (endpoint.url.includes('nownodes.io') && process.env['NOW_NODES_API']) {
376
- headers['api-key'] = process.env['NOW_NODES_API'];
377
- }
378
- payload = endpoint.type === 'unchained' ? unchainedPayload : cosmosPayload;
379
- return [4 /*yield*/, axios({
380
- url: urlRemote,
381
- headers: headers,
355
+ log.info(tag, "Broadcasting via Unchained API");
356
+ return [4 /*yield*/, axiosInstance({
357
+ url: "".concat(UNCHAINED_API, "/api/v1/send"),
382
358
  method: 'POST',
383
359
  data: payload,
384
- timeout: 10000 // 10 second timeout
360
+ timeout: 10000
385
361
  })];
386
- case 4:
387
- result2 = _a.sent();
388
- log.info(tag, '** Broadcast ** REMOTE: result: ', result2.data);
389
- log.info(tag, '** Broadcast ** REMOTE: result: ', JSON.stringify(result2.data));
390
- // Handle different response formats
391
- if (endpoint.type === 'unchained') {
392
- // Unchained API returns { txid: "hash" } on success
393
- // or throws error with response.data.message on failure
394
- if (result2.data.txid || result2.data.txHash) {
395
- output.txid = result2.data.txid || result2.data.txHash;
396
- output.success = true;
397
- output.endpoint = endpoint.name;
398
- log.info(tag, "\u2705 Broadcast SUCCESS via ".concat(endpoint.name, " - txid:"), output.txid);
399
- return [2 /*return*/, output];
400
- }
401
- else if (result2.data.message) {
402
- // Unchained error response
403
- throw new Error(result2.data.message);
404
- }
405
- }
406
- else {
407
- // Cosmos standard response format
408
- // CRITICAL: Check tx_response.code - Cosmos standard for success/error
409
- // code: 0 = success, any other code = error
410
- if (result2.data.tx_response && result2.data.tx_response.code !== 0) {
411
- errorMsg = result2.data.tx_response.raw_log || 'Transaction failed with unknown error';
412
- log.error(tag, "❌ Broadcast FAILED - code:", result2.data.tx_response.code);
413
- log.error(tag, " Error:", errorMsg);
414
- output.success = false;
415
- output.error = errorMsg;
416
- // Throw error to fail fast - don't let failed transactions proceed
417
- throw new Error("Broadcast failed (code ".concat(result2.data.tx_response.code, "): ").concat(errorMsg));
418
- }
419
- // Only set txid if transaction was successful (code === 0)
420
- if (result2.data.txhash)
421
- output.txid = result2.data.txhash;
422
- //tx_response
423
- if (result2.data.tx_response && result2.data.tx_response.txhash)
424
- output.txid = result2.data.tx_response.txhash;
362
+ case 2:
363
+ result = _b.sent();
364
+ log.info(tag, 'Broadcast response:', result.data);
365
+ // Unchained returns { txid: "hash" } on success
366
+ if (result.data.txid || result.data.txHash) {
367
+ output.txid = result.data.txid || result.data.txHash;
425
368
  output.success = true;
426
- output.endpoint = endpoint.name;
427
- log.info(tag, "\u2705 Broadcast SUCCESS via ".concat(endpoint.name, " - txid:"), output.txid);
428
- return [2 /*return*/, output];
369
+ output.endpoint = 'Unchained';
370
+ log.info(tag, "\u2705 Broadcast SUCCESS - txid: ".concat(output.txid));
429
371
  }
430
- return [3 /*break*/, 6];
431
- case 5:
432
- e_7 = _a.sent();
433
- lastError = e_7;
434
- log.error(tag, "Failed to broadcast via ".concat(endpoint.name, ":"), e_7.message);
435
- if (e_7.response) {
436
- log.error(tag, "Response status:", e_7.response.status);
437
- log.error(tag, "Response data:", e_7.response.data);
438
- // If this is a transaction validation error (not a network error), don't try other endpoints
439
- if (e_7.response.data && e_7.response.data.message &&
440
- (e_7.response.data.message.includes('insufficient') ||
441
- e_7.response.data.message.includes('invalid'))) {
442
- output.success = false;
443
- output.error = e_7.response.data.message || e_7.response.data.error;
444
- log.error(tag, "Transaction validation error - not retrying other endpoints");
445
- return [2 /*return*/, output];
446
- }
447
- }
448
- // If not last endpoint, try next one
449
- if (i < endpoints.length - 1) {
450
- log.info(tag, "Trying next endpoint...");
451
- return [3 /*break*/, 6];
372
+ else if (result.data.message) {
373
+ output.error = result.data.message;
374
+ log.error(tag, "❌ Broadcast FAILED:", result.data.message);
452
375
  }
453
- return [3 /*break*/, 6];
454
- case 6:
455
- i++;
456
- return [3 /*break*/, 2];
457
- case 7:
458
- // All endpoints failed
459
- output.success = false;
460
- if (lastError && lastError.response && lastError.response.data) {
461
- output.error = lastError.response.data.error || lastError.response.data.message || lastError.message;
376
+ return [2 /*return*/, output];
377
+ case 3:
378
+ e_6 = _b.sent();
379
+ log.error(tag, "Broadcast error:", e_6.message);
380
+ if ((_a = e_6.response) === null || _a === void 0 ? void 0 : _a.data) {
381
+ output.error = e_6.response.data.message || e_6.response.data.error || e_6.message;
382
+ log.error(tag, "Response data:", e_6.response.data);
462
383
  }
463
384
  else {
464
- output.error = (lastError === null || lastError === void 0 ? void 0 : lastError.message) || 'All broadcast endpoints failed';
385
+ output.error = e_6.message || 'Broadcast failed';
465
386
  }
466
- log.error(tag, "❌ All broadcast endpoints failed");
467
- return [2 /*return*/, output];
468
- case 8:
469
- e_8 = _a.sent();
470
- console.error(tag, "Unexpected error in broadcast: ", e_8);
471
- output.success = false;
472
- output.error = e_8.message || 'Unexpected broadcast error';
473
387
  return [2 /*return*/, output];
474
- case 9: return [2 /*return*/];
388
+ case 4: return [2 /*return*/];
475
389
  }
476
390
  });
477
391
  });
478
392
  };
479
- var get_account_info = function (address) {
393
+ // Pool endpoints use Midgard (not available in Unchained)
394
+ var get_pool = function (poolId) {
480
395
  return __awaiter(this, void 0, void 0, function () {
481
- var tag, txInfo, e_9;
396
+ var tag, params, result, e_7;
482
397
  return __generator(this, function (_a) {
483
398
  switch (_a.label) {
484
399
  case 0:
485
- tag = TAG + " | get_account_info | ";
400
+ tag = TAG + " | get_pool | ";
486
401
  _a.label = 1;
487
402
  case 1:
488
403
  _a.trys.push([1, 3, , 4]);
489
- //
490
- console.log("URL ", URL_THORNODE + '/auth/accounts/' + address);
491
- return [4 /*yield*/, axios({ method: 'GET', url: URL_THORNODE + '/auth/accounts/' + address })];
404
+ params = {
405
+ view: "full",
406
+ asset: poolId
407
+ };
408
+ return [4 /*yield*/, axiosInstance({
409
+ method: 'GET',
410
+ url: "".concat(MIDGARD_API, "/pools/detail"),
411
+ params: params,
412
+ timeout: 5000
413
+ })];
492
414
  case 2:
493
- txInfo = _a.sent();
494
- log.debug(tag, "txInfo: ", txInfo.data);
495
- return [2 /*return*/, txInfo.data];
415
+ result = _a.sent();
416
+ return [2 /*return*/, result.data];
496
417
  case 3:
497
- e_9 = _a.sent();
498
- log.error(tag, "e: ", e_9);
499
- throw e_9;
418
+ e_7 = _a.sent();
419
+ log.error(tag, "Error:", e_7.message);
420
+ throw e_7;
500
421
  case 4: return [2 /*return*/];
501
422
  }
502
423
  });
503
424
  });
504
425
  };
505
- var normalize_tx = function (tx, address) {
506
- var tag = TAG + " | normalize_tx | ";
507
- try {
508
- var output = {};
509
- var sender = void 0;
510
- var receiver = void 0;
511
- var memo = void 0;
512
- var amount = void 0;
513
- var rawlog = JSON.parse(tx.raw_log);
514
- rawlog = rawlog;
515
- //log.debug("rawlog: ",rawlog)
516
- //txTypes
517
- var txTypes = [
518
- 'send',
519
- 'receive',
520
- 'governence',
521
- 'swap',
522
- 'other'
523
- ];
524
- for (var i = 0; i < rawlog.length; i++) {
525
- var txEvents = rawlog[i];
526
- //log.debug(tag,"txEvents: ",txEvents)
527
- txEvents = txEvents.events;
528
- for (var j = 0; j < txEvents.length; j++) {
529
- var event_1 = txEvents[j];
530
- //
531
- //log.debug(tag,"event: ",event)
532
- //log.debug(tag,"attributes: ",prettyjson.render(event.attributes))
533
- //detect event type
534
- log.debug(tag, "type: ", event_1.type);
535
- switch (event_1.type) {
536
- case 'message':
537
- // ignore
538
- break;
539
- case 'transfer':
540
- log.debug(tag, "attributes: ", event_1.attributes);
541
- for (var k = 0; k < event_1.attributes.length; k++) {
542
- var attribute = event_1.attributes[k];
543
- if (attribute.key === 'recipient') {
544
- receiver = attribute.value;
545
- output.receiver = receiver;
546
- if (receiver === address)
547
- output.type = txTypes[1];
548
- }
549
- if (attribute.key === 'sender') {
550
- sender = attribute.value;
551
- output.sender = sender;
552
- if (sender === address)
553
- output.type = txTypes[0];
554
- }
555
- if (attribute.key === 'amount') {
556
- amount = attribute.value;
557
- amount = amount.replace('rune', '');
558
- output.amount = amount / 100000000;
559
- }
560
- }
561
- break;
562
- default:
563
- // code block
564
- }
565
- }
566
- // console.log("log: ",prettyjson.render(log))
567
- }
568
- return output;
569
- }
570
- catch (e) {
571
- log.error(tag, "e: ", e);
572
- throw e;
573
- }
574
- };
575
- var get_txs_by_address = function (address) {
426
+ var get_pools = function () {
576
427
  return __awaiter(this, void 0, void 0, function () {
577
- var tag, output, url, resultSends, sends, i, tx, resultRecieves, receives, i, tx, e_10;
428
+ var tag, result, e_8;
578
429
  return __generator(this, function (_a) {
579
430
  switch (_a.label) {
580
431
  case 0:
581
- tag = TAG + " | get_txs_by_address | ";
432
+ tag = TAG + " | get_pools | ";
582
433
  _a.label = 1;
583
434
  case 1:
584
- _a.trys.push([1, 4, , 5]);
585
- output = [];
586
- url = URL_THORNODE + '/txs?message.sender=' + address;
587
- log.debug(tag, "url: ", url);
588
- return [4 /*yield*/, axios({
589
- url: url,
590
- method: 'GET'
591
- })];
592
- case 2:
593
- resultSends = _a.sent();
594
- sends = resultSends.data;
595
- log.debug('sends: ', sends);
596
- if (!sends.txs)
597
- sends.txs = [];
598
- // TODO//pagnation
599
- for (i = 0; i < (sends === null || sends === void 0 ? void 0 : sends.txs.length); i++) {
600
- tx = sends.txs[i];
601
- //pretty json
602
- //normalize
603
- tx = normalize_tx(tx, address);
604
- output.push(tx);
605
- }
606
- //receives
607
- url = URL_THORNODE + '/txs?transfer.recipient=' + address;
608
- console.log("URL_THORNODE: ", url);
609
- return [4 /*yield*/, axios({
610
- url: url,
611
- method: 'GET'
435
+ _a.trys.push([1, 3, , 4]);
436
+ return [4 /*yield*/, axiosInstance({
437
+ method: 'GET',
438
+ url: "".concat(MIDGARD_API, "/pools"),
439
+ timeout: 5000
612
440
  })];
613
- case 3:
614
- resultRecieves = _a.sent();
615
- receives = resultRecieves.data;
616
- if (!receives.txs)
617
- receives.txs = [];
618
- log.debug('receives: ', receives);
619
- for (i = 0; i < (receives === null || receives === void 0 ? void 0 : receives.txs.length); i++) {
620
- tx = receives.txs[i];
621
- //normalize
622
- tx = normalize_tx(tx, address);
623
- output.push(tx);
624
- }
625
- return [2 /*return*/, output];
626
- case 4:
627
- e_10 = _a.sent();
628
- log.error(tag, "e: ", e_10);
629
- throw e_10;
630
- case 5: return [2 /*return*/];
631
- }
632
- });
633
- });
634
- };
635
- var get_balance = function (address) {
636
- return __awaiter(this, void 0, void 0, function () {
637
- var tag, output, accountInfo, i, entry, e_11, e_12;
638
- var _a;
639
- return __generator(this, function (_b) {
640
- switch (_b.label) {
641
- case 0:
642
- tag = TAG + " | get_balance | ";
643
- _b.label = 1;
644
- case 1:
645
- _b.trys.push([1, 6, , 7]);
646
- output = 0;
647
- _b.label = 2;
648
- case 2:
649
- _b.trys.push([2, 4, , 5]);
650
- return [4 /*yield*/, axios({ method: 'GET', url: URL_THORNODE + '/bank/balances/' + address })];
651
- case 3:
652
- accountInfo = _b.sent();
653
- log.info(tag, "accountInfo: ", accountInfo.data);
654
- //
655
- if ((_a = accountInfo.data) === null || _a === void 0 ? void 0 : _a.result) {
656
- for (i = 0; i < accountInfo.data.result.length; i++) {
657
- entry = accountInfo.data.result[i];
658
- if (entry.denom === 'cacao') {
659
- output = entry.amount;
660
- }
661
- }
662
- }
663
- output = output / BASE_THOR;
664
- return [3 /*break*/, 5];
665
- case 4:
666
- e_11 = _b.sent();
667
- return [3 /*break*/, 5];
668
- case 5: return [2 /*return*/, output];
669
- case 6:
670
- e_12 = _b.sent();
671
- log.error(tag, "e: ", e_12);
672
- throw e_12;
673
- case 7: return [2 /*return*/];
674
- }
675
- });
676
- });
677
- };
678
- var get_balances = function (address) {
679
- return __awaiter(this, void 0, void 0, function () {
680
- var tag, output, accountInfo, i, entry, e_13, e_14;
681
- var _a;
682
- return __generator(this, function (_b) {
683
- switch (_b.label) {
684
- case 0:
685
- tag = TAG + " | get_balances | ";
686
- _b.label = 1;
687
- case 1:
688
- _b.trys.push([1, 6, , 7]);
689
- output = [];
690
- _b.label = 2;
691
441
  case 2:
692
- _b.trys.push([2, 4, , 5]);
693
- return [4 /*yield*/, axios({ method: 'GET', url: URL_THORNODE + '/bank/balances/' + address })];
442
+ result = _a.sent();
443
+ return [2 /*return*/, result.data];
694
444
  case 3:
695
- accountInfo = _b.sent();
696
- log.info(tag, "accountInfo: ", accountInfo.data);
697
- //
698
- if ((_a = accountInfo.data) === null || _a === void 0 ? void 0 : _a.result) {
699
- for (i = 0; i < accountInfo.data.result.length; i++) {
700
- entry = accountInfo.data.result[i];
701
- if (entry.denom === 'cacao') {
702
- output.push({
703
- denom: entry.denom,
704
- amountBase: entry.amount,
705
- amount: entry.amount / 10000000000,
706
- decimals: 10
707
- });
708
- }
709
- if (entry.denom === 'maya') {
710
- output.push({
711
- denom: entry.denom,
712
- amountBase: entry.amount,
713
- amount: entry.amount / 10000,
714
- decimals: 4
715
- });
716
- }
717
- }
718
- }
719
- return [3 /*break*/, 5];
720
- case 4:
721
- e_13 = _b.sent();
722
- return [3 /*break*/, 5];
723
- case 5: return [2 /*return*/, output];
724
- case 6:
725
- e_14 = _b.sent();
726
- log.error(tag, "e: ", e_14);
727
- throw e_14;
728
- case 7: return [2 /*return*/];
445
+ e_8 = _a.sent();
446
+ log.error(tag, "Error:", e_8.message);
447
+ throw e_8;
448
+ case 4: return [2 /*return*/];
729
449
  }
730
450
  });
731
451
  });
732
452
  };
733
- var get_node_info_verbose = function () {
453
+ var get_pool_addresses = function () {
734
454
  return __awaiter(this, void 0, void 0, function () {
735
- var tag, output, syncInfo, nodeInfo, lastBlock, e_15;
455
+ var tag;
736
456
  return __generator(this, function (_a) {
737
- switch (_a.label) {
738
- case 0:
739
- tag = TAG + " | get_node_info | ";
740
- _a.label = 1;
741
- case 1:
742
- _a.trys.push([1, 5, , 6]);
743
- output = {};
744
- return [4 /*yield*/, axios({ method: 'GET', url: URL_THORNODE + '/syncing' })];
745
- case 2:
746
- syncInfo = _a.sent();
747
- log.debug(tag, "syncInfo: ", syncInfo.data);
748
- output.isSyncing = syncInfo.data;
749
- return [4 /*yield*/, axios({ method: 'GET', url: URL_THORNODE + '/node_info' })];
750
- case 3:
751
- nodeInfo = _a.sent();
752
- log.debug(tag, "nodeInfo: ", nodeInfo.data);
753
- output = nodeInfo.data;
754
- return [4 /*yield*/, axios({ method: 'GET', url: URL_THORNODE + '/blocks/latest' })];
755
- case 4:
756
- lastBlock = _a.sent();
757
- log.debug(tag, "lastBlock: ", lastBlock.data);
758
- //let height
759
- output.height = lastBlock.data.block.header.height;
760
- return [2 /*return*/, output];
761
- case 5:
762
- e_15 = _a.sent();
763
- log.error(tag, "e: ", e_15);
764
- throw e_15;
765
- case 6: return [2 /*return*/];
457
+ tag = TAG + " | get_pool_addresses | ";
458
+ try {
459
+ // This endpoint might not be available, would need node access
460
+ log.warn(tag, "Pool addresses endpoint may require direct node access");
461
+ throw new Error("Pool addresses not available in Unchained API");
462
+ }
463
+ catch (e) {
464
+ log.error(tag, "Error:", e.message);
465
+ throw e;
766
466
  }
467
+ return [2 /*return*/];
767
468
  });
768
469
  });
769
470
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pioneer-platform/maya-network",
3
- "version": "8.11.1",
3
+ "version": "8.12.1",
4
4
  "main": "./lib/index.js",
5
5
  "types": "./lib/index.d.ts",
6
6
  "scripts": {