@pioneer-platform/maya-network 8.11.0 → 8.12.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.
@@ -1,2 +1 @@
1
-
2
- $ tsc -p .
1
+ $ tsc -p .
package/CHANGELOG.md CHANGED
@@ -1,5 +1,30 @@
1
1
  # @pioneer-platform/maya-network
2
2
 
3
+ ## 8.12.0
4
+
5
+ ### Minor Changes
6
+
7
+ - Migrate MayaChain network module to Unchained API
8
+
9
+ - Replace direct node calls with ShapeShift Unchained API
10
+ - Remove verbose error logging and 503 spam
11
+ - Add proper timeouts to all requests (5-10s)
12
+ - Reduce code size by 50% (646 → 320 lines)
13
+ - Improve reliability and performance
14
+ - Keep Midgard API for pool data only
15
+ - Add comprehensive test suite and documentation
16
+
17
+ ## 8.11.1
18
+
19
+ ### Patch Changes
20
+
21
+ - 3f2da9a: Add ShapeShift MayaChain Unchained API integration with dual broadcast support
22
+
23
+ - Added MayaChain Unchained endpoints to pioneer-nodes seed configuration
24
+ - Implemented dual broadcast in maya-network (MayaNode + ShapeShift Unchained + NowNodes fallbacks)
25
+ - Added endpoint-specific payload formatting (Cosmos vs Unchained API formats)
26
+ - Updated unchained integration tests for MayaChain broadcast validation
27
+
3
28
  ## 8.11.0
4
29
 
5
30
  ### Minor 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,32 +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 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;
12
11
  /**********************************
13
- // Lib
12
+ // Implementation
14
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>;
15
21
  declare const get_pool: (poolId: string) => Promise<any>;
16
22
  declare const get_pools: () => Promise<any>;
17
- declare const get_pool_addresses: () => Promise<any>;
18
- declare let get_last_block: () => Promise<any>;
19
- declare let get_block_height: () => Promise<any>;
20
- declare let get_transaction: (txid: string) => Promise<any>;
21
- declare let broadcast_transaction: (tx: string) => Promise<any>;
22
- declare let get_account_info: (address: string) => Promise<any>;
23
- declare let normalize_tx: (tx: any, address?: string) => any;
24
- declare let get_txs_by_address: (address: string) => Promise<any>;
25
- declare let get_balance: (address: string) => Promise<number>;
26
- declare let get_balances: (address: string) => Promise<{
27
- denom: any;
28
- amountBase: any;
29
- amount: number;
30
- decimals: number;
31
- }[]>;
32
- declare let get_node_info_verbose: () => Promise<any>;
23
+ declare const get_pool_addresses: () => Promise<never>;
package/lib/index.js CHANGED
@@ -1,4 +1,10 @@
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
+ */
2
8
  var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
9
  function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
10
  return new (P || (P = Promise))(function (resolve, reject) {
@@ -35,52 +41,39 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
35
41
  if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
36
42
  }
37
43
  };
38
- /*
39
- const thorMainnetClient: CosmosSDKClient = new CosmosSDKClient({
40
- server: 'http://104.248.96.152:1317',
41
- chainId: 'thorchain',
42
- prefix: 'thor',
43
- derive_path: "44'/931'/0'/0/0",
44
- })
45
-
46
-
47
- get nodes
48
- curl https://testnet-seed.thorchain.info
49
-
50
- //testnet
51
- https://main.d3mbd42yfy75lz.amplifyapp.com/#/nodes
52
-
53
- */
54
- var TAG = " | thorchain-api | ";
55
- var prettyjson = require('prettyjson');
56
- require("dotenv").config({ path: '../../../.env' });
44
+ var TAG = " | mayachain-api | ";
45
+ var log = require('@pioneer-platform/loggerdog')();
57
46
  var axiosLib = require('axios');
58
- var Axios = axiosLib.default || axiosLib;
47
+ var axios = axiosLib.default || axiosLib;
59
48
  var https = require('https');
60
- var axios = Axios.create({
49
+ // Create axios instance with retry logic but minimal logging
50
+ var axiosInstance = axios.create({
61
51
  httpsAgent: new https.Agent({
62
52
  rejectUnauthorized: false
63
53
  })
64
54
  });
65
55
  var axiosRetry = require('axios-retry');
66
- axiosRetry(axios, {
67
- retries: 3, // number of retries
56
+ axiosRetry(axiosInstance, {
57
+ retries: 2,
68
58
  retryDelay: function (retryCount) {
69
- console.log("retry attempt: ".concat(retryCount));
70
- return retryCount * 2000; // time interval between retries
59
+ return retryCount * 1000;
71
60
  },
72
61
  retryCondition: function (error) {
73
- console.error(error);
74
- // if retry condition is not specified, by default idempotent requests are retried
75
- return error.response.status === 503;
62
+ var _a;
63
+ return ((_a = error.response) === null || _a === void 0 ? void 0 : _a.status) === 503;
76
64
  },
65
+ onRetry: function (retryCount, error) {
66
+ log.debug(TAG, "Retry ".concat(retryCount, "/2: ").concat(error.message));
67
+ }
77
68
  });
78
- var log = require('@pioneer-platform/loggerdog')();
79
- var URL_THORNODE = 'https://mayanode.mayachain.info';
80
- var URL_MIDGARD = 'https://midgard.mayachain.info/v2';
81
- var BASE_THOR = 10000000000;
69
+ // Unchained API endpoint
70
+ var UNCHAINED_API = 'https://api.mayachain.shapeshift.com';
71
+ // Fallback to Midgard for pool data (not available in Unchained)
72
+ var MIDGARD_API = 'https://midgard.mayachain.info/v2';
73
+ // Base unit conversion (10 decimal places for CACAO)
74
+ var BASE_MAYA = 10000000000;
82
75
  /**********************************
83
- // Module
76
+ // Module Exports
84
77
  //**********************************/
85
78
  module.exports = {
86
79
  init: function (url, settings) {
@@ -90,7 +83,7 @@ module.exports = {
90
83
  return true;
91
84
  },
92
85
  info: function () {
93
- return get_node_info_verbose();
86
+ return get_info();
94
87
  },
95
88
  getBalance: function (address) {
96
89
  return get_balance(address);
@@ -101,12 +94,6 @@ module.exports = {
101
94
  getAccount: function (address) {
102
95
  return get_account_info(address);
103
96
  },
104
- getLastBlock: function () {
105
- return get_last_block();
106
- },
107
- getBlockHeight: function () {
108
- return get_block_height();
109
- },
110
97
  getAccountInfo: function (address) {
111
98
  return get_account_info(address);
112
99
  },
@@ -133,148 +120,174 @@ module.exports = {
133
120
  },
134
121
  };
135
122
  /**********************************
136
- // Lib
123
+ // Implementation
137
124
  //**********************************/
138
- var get_pool = function (poolId) {
125
+ var get_info = function () {
139
126
  return __awaiter(this, void 0, void 0, function () {
140
- var tag, params, body, resp, e_1;
127
+ var tag, result, e_1;
141
128
  return __generator(this, function (_a) {
142
129
  switch (_a.label) {
143
130
  case 0:
144
- tag = TAG + " | get_pool | ";
131
+ tag = TAG + " | get_info | ";
145
132
  _a.label = 1;
146
133
  case 1:
147
134
  _a.trys.push([1, 3, , 4]);
148
- params = {
149
- view: "full",
150
- asset: poolId
151
- };
152
- body = {
153
- method: 'GET',
154
- url: URL_MIDGARD + "/pools/detail",
155
- headers: { 'content-type': 'application/json' },
156
- params: params
157
- };
158
- log.debug(body);
159
- return [4 /*yield*/, axios(body)];
135
+ return [4 /*yield*/, axiosInstance({
136
+ method: 'GET',
137
+ url: "".concat(UNCHAINED_API, "/api/v1/info"),
138
+ timeout: 5000
139
+ })];
160
140
  case 2:
161
- resp = _a.sent();
162
- return [2 /*return*/, resp.data];
141
+ result = _a.sent();
142
+ return [2 /*return*/, result.data];
163
143
  case 3:
164
144
  e_1 = _a.sent();
165
- log.error(tag, "e: ", e_1);
145
+ log.error(tag, "Error:", e_1.message);
166
146
  throw e_1;
167
147
  case 4: return [2 /*return*/];
168
148
  }
169
149
  });
170
150
  });
171
151
  };
172
- var get_pools = function () {
152
+ var get_account_info = function (address) {
173
153
  return __awaiter(this, void 0, void 0, function () {
174
- var tag, body, resp, e_2;
154
+ var tag, result, e_2;
175
155
  return __generator(this, function (_a) {
176
156
  switch (_a.label) {
177
157
  case 0:
178
- tag = TAG + " | get_pools | ";
158
+ tag = TAG + " | get_account_info | ";
179
159
  _a.label = 1;
180
160
  case 1:
181
161
  _a.trys.push([1, 3, , 4]);
182
- body = {
183
- method: 'GET',
184
- url: URL_MIDGARD + "/pools",
185
- headers: { 'content-type': 'application/json' },
186
- // body: {account_name: actor},
187
- // json: true
188
- };
189
- log.debug(body.url);
190
- return [4 /*yield*/, axios(body)];
162
+ return [4 /*yield*/, axiosInstance({
163
+ method: 'GET',
164
+ url: "".concat(UNCHAINED_API, "/api/v1/account/").concat(address),
165
+ timeout: 5000
166
+ })];
191
167
  case 2:
192
- resp = _a.sent();
193
- return [2 /*return*/, resp.data];
168
+ result = _a.sent();
169
+ return [2 /*return*/, result.data];
194
170
  case 3:
195
171
  e_2 = _a.sent();
196
- log.error(tag, "e: ", e_2);
172
+ log.error(tag, "Error:", e_2.message);
197
173
  throw e_2;
198
174
  case 4: return [2 /*return*/];
199
175
  }
200
176
  });
201
177
  });
202
178
  };
203
- //https://testnet.thornode.thorchain.info/thorchain/inbound_addresses
204
- var get_pool_addresses = function () {
179
+ var get_balance = function (address) {
205
180
  return __awaiter(this, void 0, void 0, function () {
206
- var tag, output, body, resp, e_3;
181
+ var tag, accountInfo, balance, e_3;
207
182
  return __generator(this, function (_a) {
208
183
  switch (_a.label) {
209
184
  case 0:
210
- tag = TAG + " | get_pool_addresses | ";
185
+ tag = TAG + " | get_balance | ";
211
186
  _a.label = 1;
212
187
  case 1:
213
188
  _a.trys.push([1, 3, , 4]);
214
- output = {};
215
- body = {
216
- method: 'GET',
217
- url: URL_THORNODE + "/thorchain/inbound_addresses",
218
- headers: { 'content-type': 'application/json' },
219
- // body: {account_name: actor},
220
- // json: true
221
- };
222
- log.debug(body);
223
- return [4 /*yield*/, axios(body)];
189
+ return [4 /*yield*/, get_account_info(address)
190
+ // Parse balance from string to number
191
+ ];
224
192
  case 2:
225
- resp = _a.sent();
226
- return [2 /*return*/, resp.data];
193
+ accountInfo = _a.sent();
194
+ balance = parseFloat(accountInfo.balance || '0');
195
+ // Convert from base units to CACAO
196
+ return [2 /*return*/, balance / BASE_MAYA];
227
197
  case 3:
228
198
  e_3 = _a.sent();
229
- log.error(tag, "e: ", e_3);
230
- return [3 /*break*/, 4];
199
+ log.error(tag, "Error:", e_3.message);
200
+ throw e_3;
231
201
  case 4: return [2 /*return*/];
232
202
  }
233
203
  });
234
204
  });
235
205
  };
236
- var get_last_block = function () {
206
+ var get_balances = function (address) {
237
207
  return __awaiter(this, void 0, void 0, function () {
238
- var tag, lastBlock, e_4;
239
- return __generator(this, function (_a) {
240
- switch (_a.label) {
208
+ var tag, accountInfo, output, cacaoBalance, _i, _a, asset, e_4;
209
+ return __generator(this, function (_b) {
210
+ switch (_b.label) {
241
211
  case 0:
242
- tag = TAG + " | get_last_block | ";
243
- _a.label = 1;
212
+ tag = TAG + " | get_balances | ";
213
+ _b.label = 1;
244
214
  case 1:
245
- _a.trys.push([1, 3, , 4]);
246
- return [4 /*yield*/, axios({ method: 'GET', url: URL_THORNODE + '/blocks/latest' })];
215
+ _b.trys.push([1, 3, , 4]);
216
+ return [4 /*yield*/, get_account_info(address)];
247
217
  case 2:
248
- lastBlock = _a.sent();
249
- log.debug(tag, "lastBlock: ", lastBlock.data);
250
- return [2 /*return*/, lastBlock.data.block];
218
+ accountInfo = _b.sent();
219
+ output = [];
220
+ cacaoBalance = parseFloat(accountInfo.balance || '0');
221
+ if (cacaoBalance > 0) {
222
+ output.push({
223
+ denom: 'cacao',
224
+ amountBase: accountInfo.balance,
225
+ amount: cacaoBalance / BASE_MAYA,
226
+ decimals: 10
227
+ });
228
+ }
229
+ // Parse assets array if present (MAYA and other assets)
230
+ if (accountInfo.assets && Array.isArray(accountInfo.assets)) {
231
+ for (_i = 0, _a = accountInfo.assets; _i < _a.length; _i++) {
232
+ asset = _a[_i];
233
+ if (asset.denom === 'maya') {
234
+ output.push({
235
+ denom: asset.denom,
236
+ amountBase: asset.amount,
237
+ amount: parseFloat(asset.amount) / 10000, // 4 decimals for MAYA
238
+ decimals: 4
239
+ });
240
+ }
241
+ else if (asset.denom === 'cacao') {
242
+ // Skip if already added from main balance
243
+ continue;
244
+ }
245
+ else {
246
+ output.push({
247
+ denom: asset.denom,
248
+ amountBase: asset.amount,
249
+ amount: parseFloat(asset.amount),
250
+ decimals: 0
251
+ });
252
+ }
253
+ }
254
+ }
255
+ return [2 /*return*/, output];
251
256
  case 3:
252
- e_4 = _a.sent();
253
- log.error(tag, "e: ", e_4);
257
+ e_4 = _b.sent();
258
+ log.error(tag, "Error:", e_4.message);
254
259
  throw e_4;
255
260
  case 4: return [2 /*return*/];
256
261
  }
257
262
  });
258
263
  });
259
264
  };
260
- var get_block_height = function () {
261
- return __awaiter(this, void 0, void 0, function () {
262
- var tag, lastBlock, e_5;
265
+ var get_txs_by_address = function (address_1, cursor_1) {
266
+ return __awaiter(this, arguments, void 0, function (address, cursor, pageSize) {
267
+ var tag, params, result, e_5;
268
+ if (pageSize === void 0) { pageSize = 50; }
263
269
  return __generator(this, function (_a) {
264
270
  switch (_a.label) {
265
271
  case 0:
266
- tag = TAG + " | get_block_height | ";
272
+ tag = TAG + " | get_txs_by_address | ";
267
273
  _a.label = 1;
268
274
  case 1:
269
275
  _a.trys.push([1, 3, , 4]);
270
- return [4 /*yield*/, axios({ method: 'GET', url: URL_THORNODE + '/blocks/latest' })];
276
+ params = { pageSize: pageSize };
277
+ if (cursor)
278
+ params.cursor = cursor;
279
+ return [4 /*yield*/, axiosInstance({
280
+ method: 'GET',
281
+ url: "".concat(UNCHAINED_API, "/api/v1/account/").concat(address, "/txs"),
282
+ params: params,
283
+ timeout: 10000
284
+ })];
271
285
  case 2:
272
- lastBlock = _a.sent();
273
- log.debug(tag, "lastBlock: ", lastBlock.data);
274
- return [2 /*return*/, lastBlock.data.block.header.height];
286
+ result = _a.sent();
287
+ return [2 /*return*/, result.data];
275
288
  case 3:
276
289
  e_5 = _a.sent();
277
- log.error(tag, "e: ", e_5);
290
+ log.error(tag, "Error:", e_5.message);
278
291
  throw e_5;
279
292
  case 4: return [2 /*return*/];
280
293
  }
@@ -283,406 +296,151 @@ var get_block_height = function () {
283
296
  };
284
297
  var get_transaction = function (txid) {
285
298
  return __awaiter(this, void 0, void 0, function () {
286
- var tag, txInfo, e_6, output;
299
+ var tag;
287
300
  return __generator(this, function (_a) {
288
- switch (_a.label) {
289
- case 0:
290
- tag = TAG + " | get_transaction | ";
291
- _a.label = 1;
292
- case 1:
293
- _a.trys.push([1, 3, , 4]);
294
- return [4 /*yield*/, axios({ method: 'GET', url: URL_THORNODE + '/txs/' + txid })];
295
- case 2:
296
- txInfo = _a.sent();
297
- log.debug(tag, "txInfo: ", txInfo.data);
298
- return [2 /*return*/, txInfo.data];
299
- case 3:
300
- e_6 = _a.sent();
301
- // log.error(tag,e.response.data)
302
- // log.error(tag,e.response.data.error)
303
- if (e_6.response.status === 404) {
304
- output = {};
305
- output.success = false;
306
- output.error = e_6.response.data.error;
307
- return [2 /*return*/, output];
308
- }
309
- else {
310
- throw Error(e_6);
311
- }
312
- return [3 /*break*/, 4];
313
- case 4: return [2 /*return*/];
301
+ tag = TAG + " | get_transaction | ";
302
+ try {
303
+ // Unchained doesn't have a direct tx lookup endpoint
304
+ // Would need to implement via account txs or use Midgard/node fallback
305
+ log.warn(tag, "Transaction lookup not implemented in Unchained API, use Midgard or node directly");
306
+ throw new Error("Transaction lookup not available in Unchained API");
307
+ }
308
+ catch (e) {
309
+ log.error(tag, "Error:", e.message);
310
+ throw e;
314
311
  }
312
+ return [2 /*return*/];
315
313
  });
316
314
  });
317
315
  };
318
316
  var broadcast_transaction = function (tx) {
319
317
  return __awaiter(this, void 0, void 0, function () {
320
- var tag, output, payload, urlRemote, result2, errorMsg, e_7, e_8;
321
- return __generator(this, function (_a) {
322
- switch (_a.label) {
318
+ var tag, output, payload, result, e_6;
319
+ var _a;
320
+ return __generator(this, function (_b) {
321
+ switch (_b.label) {
323
322
  case 0:
324
323
  tag = TAG + " | broadcast_transaction | ";
325
- output = {};
326
- _a.label = 1;
324
+ output = { success: false };
325
+ _b.label = 1;
327
326
  case 1:
328
- _a.trys.push([1, 6, , 7]);
329
- log.debug(tag, "CHECKPOINT 1");
330
- output.success = false;
331
- _a.label = 2;
332
- case 2:
333
- _a.trys.push([2, 4, , 5]);
327
+ _b.trys.push([1, 3, , 4]);
334
328
  payload = {
335
- // "tx_bytes": btoa(tx),
336
- // "tx_bytes":broadcastTx,
337
- "tx_bytes": tx,
338
- "mode": "BROADCAST_MODE_SYNC"
329
+ rawTx: tx
339
330
  };
340
- urlRemote = URL_THORNODE + '/cosmos/tx/v1beta1/txs';
341
- // let urlRemote = URL_GAIAD+ '/txs'
342
- log.info(tag, "urlRemote: ", urlRemote);
343
- return [4 /*yield*/, axios({
344
- url: urlRemote,
345
- headers: {
346
- 'api-key': process.env['NOW_NODES_API'],
347
- 'Content-Type': 'application/json'
348
- },
331
+ log.info(tag, "Broadcasting via Unchained API");
332
+ return [4 /*yield*/, axiosInstance({
333
+ url: "".concat(UNCHAINED_API, "/api/v1/send"),
349
334
  method: 'POST',
350
335
  data: payload,
336
+ timeout: 10000
351
337
  })];
352
- case 3:
353
- result2 = _a.sent();
354
- log.info(tag, '** Broadcast ** REMOTE: result: ', result2.data);
355
- log.info(tag, '** Broadcast ** REMOTE: result: ', JSON.stringify(result2.data));
356
- // CRITICAL: Check tx_response.code - Cosmos standard for success/error
357
- // code: 0 = success, any other code = error
358
- if (result2.data.tx_response && result2.data.tx_response.code !== 0) {
359
- errorMsg = result2.data.tx_response.raw_log || 'Transaction failed with unknown error';
360
- log.error(tag, " Broadcast FAILED - code:", result2.data.tx_response.code);
361
- log.error(tag, " Error:", errorMsg);
362
- output.success = false;
363
- output.error = errorMsg;
364
- // Throw error to fail fast - don't let failed transactions proceed
365
- throw new Error("Broadcast failed (code ".concat(result2.data.tx_response.code, "): ").concat(errorMsg));
338
+ case 2:
339
+ result = _b.sent();
340
+ log.info(tag, 'Broadcast response:', result.data);
341
+ // Unchained returns { txid: "hash" } on success
342
+ if (result.data.txid || result.data.txHash) {
343
+ output.txid = result.data.txid || result.data.txHash;
344
+ output.success = true;
345
+ output.endpoint = 'Unchained';
346
+ log.info(tag, "\u2705 Broadcast SUCCESS - txid: ".concat(output.txid));
347
+ }
348
+ else if (result.data.message) {
349
+ output.error = result.data.message;
350
+ log.error(tag, "❌ Broadcast FAILED:", result.data.message);
366
351
  }
367
- // Only set txid if transaction was successful (code === 0)
368
- if (result2.data.txhash)
369
- output.txid = result2.data.txhash;
370
- //tx_response
371
- if (result2.data.tx_response.txhash)
372
- output.txid = result2.data.tx_response.txhash;
373
- output.success = true;
374
- log.info(tag, "✅ Broadcast SUCCESS - txid:", output.txid);
375
352
  return [2 /*return*/, output];
376
- case 4:
377
- e_7 = _a.sent();
378
- //log.error(tag,"failed second broadcast e: ",e.response)
379
- log.error(tag, e_7);
380
- log.error(tag, e_7.response);
381
- log.error(tag, e_7.response.data);
382
- log.error(tag, e_7.response.data.error);
383
- log.error(tag, e_7.response.data.error.indexOf('RPC error -32603 - Internal error: Tx already exists in cache'));
384
- //throw e
385
- output.success = false;
386
- output.error = e_7.response.data.error;
387
- return [3 /*break*/, 5];
388
- case 5: return [2 /*return*/, output];
389
- case 6:
390
- e_8 = _a.sent();
391
- console.error(tag, "throw error: ", e_8);
353
+ case 3:
354
+ e_6 = _b.sent();
355
+ log.error(tag, "Broadcast error:", e_6.message);
356
+ if ((_a = e_6.response) === null || _a === void 0 ? void 0 : _a.data) {
357
+ output.error = e_6.response.data.message || e_6.response.data.error || e_6.message;
358
+ log.error(tag, "Response data:", e_6.response.data);
359
+ }
360
+ else {
361
+ output.error = e_6.message || 'Broadcast failed';
362
+ }
392
363
  return [2 /*return*/, output];
393
- case 7: return [2 /*return*/];
364
+ case 4: return [2 /*return*/];
394
365
  }
395
366
  });
396
367
  });
397
368
  };
398
- var get_account_info = function (address) {
369
+ // Pool endpoints use Midgard (not available in Unchained)
370
+ var get_pool = function (poolId) {
399
371
  return __awaiter(this, void 0, void 0, function () {
400
- var tag, txInfo, e_9;
372
+ var tag, params, result, e_7;
401
373
  return __generator(this, function (_a) {
402
374
  switch (_a.label) {
403
375
  case 0:
404
- tag = TAG + " | get_account_info | ";
376
+ tag = TAG + " | get_pool | ";
405
377
  _a.label = 1;
406
378
  case 1:
407
379
  _a.trys.push([1, 3, , 4]);
408
- //
409
- console.log("URL ", URL_THORNODE + '/auth/accounts/' + address);
410
- return [4 /*yield*/, axios({ method: 'GET', url: URL_THORNODE + '/auth/accounts/' + address })];
380
+ params = {
381
+ view: "full",
382
+ asset: poolId
383
+ };
384
+ return [4 /*yield*/, axiosInstance({
385
+ method: 'GET',
386
+ url: "".concat(MIDGARD_API, "/pools/detail"),
387
+ params: params,
388
+ timeout: 5000
389
+ })];
411
390
  case 2:
412
- txInfo = _a.sent();
413
- log.debug(tag, "txInfo: ", txInfo.data);
414
- return [2 /*return*/, txInfo.data];
391
+ result = _a.sent();
392
+ return [2 /*return*/, result.data];
415
393
  case 3:
416
- e_9 = _a.sent();
417
- log.error(tag, "e: ", e_9);
418
- throw e_9;
394
+ e_7 = _a.sent();
395
+ log.error(tag, "Error:", e_7.message);
396
+ throw e_7;
419
397
  case 4: return [2 /*return*/];
420
398
  }
421
399
  });
422
400
  });
423
401
  };
424
- var normalize_tx = function (tx, address) {
425
- var tag = TAG + " | normalize_tx | ";
426
- try {
427
- var output = {};
428
- var sender = void 0;
429
- var receiver = void 0;
430
- var memo = void 0;
431
- var amount = void 0;
432
- var rawlog = JSON.parse(tx.raw_log);
433
- rawlog = rawlog;
434
- //log.debug("rawlog: ",rawlog)
435
- //txTypes
436
- var txTypes = [
437
- 'send',
438
- 'receive',
439
- 'governence',
440
- 'swap',
441
- 'other'
442
- ];
443
- for (var i = 0; i < rawlog.length; i++) {
444
- var txEvents = rawlog[i];
445
- //log.debug(tag,"txEvents: ",txEvents)
446
- txEvents = txEvents.events;
447
- for (var j = 0; j < txEvents.length; j++) {
448
- var event_1 = txEvents[j];
449
- //
450
- //log.debug(tag,"event: ",event)
451
- //log.debug(tag,"attributes: ",prettyjson.render(event.attributes))
452
- //detect event type
453
- log.debug(tag, "type: ", event_1.type);
454
- switch (event_1.type) {
455
- case 'message':
456
- // ignore
457
- break;
458
- case 'transfer':
459
- log.debug(tag, "attributes: ", event_1.attributes);
460
- for (var k = 0; k < event_1.attributes.length; k++) {
461
- var attribute = event_1.attributes[k];
462
- if (attribute.key === 'recipient') {
463
- receiver = attribute.value;
464
- output.receiver = receiver;
465
- if (receiver === address)
466
- output.type = txTypes[1];
467
- }
468
- if (attribute.key === 'sender') {
469
- sender = attribute.value;
470
- output.sender = sender;
471
- if (sender === address)
472
- output.type = txTypes[0];
473
- }
474
- if (attribute.key === 'amount') {
475
- amount = attribute.value;
476
- amount = amount.replace('rune', '');
477
- output.amount = amount / 100000000;
478
- }
479
- }
480
- break;
481
- default:
482
- // code block
483
- }
484
- }
485
- // console.log("log: ",prettyjson.render(log))
486
- }
487
- return output;
488
- }
489
- catch (e) {
490
- log.error(tag, "e: ", e);
491
- throw e;
492
- }
493
- };
494
- var get_txs_by_address = function (address) {
402
+ var get_pools = function () {
495
403
  return __awaiter(this, void 0, void 0, function () {
496
- var tag, output, url, resultSends, sends, i, tx, resultRecieves, receives, i, tx, e_10;
404
+ var tag, result, e_8;
497
405
  return __generator(this, function (_a) {
498
406
  switch (_a.label) {
499
407
  case 0:
500
- tag = TAG + " | get_txs_by_address | ";
408
+ tag = TAG + " | get_pools | ";
501
409
  _a.label = 1;
502
410
  case 1:
503
- _a.trys.push([1, 4, , 5]);
504
- output = [];
505
- url = URL_THORNODE + '/txs?message.sender=' + address;
506
- log.debug(tag, "url: ", url);
507
- return [4 /*yield*/, axios({
508
- url: url,
509
- method: 'GET'
510
- })];
511
- case 2:
512
- resultSends = _a.sent();
513
- sends = resultSends.data;
514
- log.debug('sends: ', sends);
515
- if (!sends.txs)
516
- sends.txs = [];
517
- // TODO//pagnation
518
- for (i = 0; i < (sends === null || sends === void 0 ? void 0 : sends.txs.length); i++) {
519
- tx = sends.txs[i];
520
- //pretty json
521
- //normalize
522
- tx = normalize_tx(tx, address);
523
- output.push(tx);
524
- }
525
- //receives
526
- url = URL_THORNODE + '/txs?transfer.recipient=' + address;
527
- console.log("URL_THORNODE: ", url);
528
- return [4 /*yield*/, axios({
529
- url: url,
530
- method: 'GET'
411
+ _a.trys.push([1, 3, , 4]);
412
+ return [4 /*yield*/, axiosInstance({
413
+ method: 'GET',
414
+ url: "".concat(MIDGARD_API, "/pools"),
415
+ timeout: 5000
531
416
  })];
532
- case 3:
533
- resultRecieves = _a.sent();
534
- receives = resultRecieves.data;
535
- if (!receives.txs)
536
- receives.txs = [];
537
- log.debug('receives: ', receives);
538
- for (i = 0; i < (receives === null || receives === void 0 ? void 0 : receives.txs.length); i++) {
539
- tx = receives.txs[i];
540
- //normalize
541
- tx = normalize_tx(tx, address);
542
- output.push(tx);
543
- }
544
- return [2 /*return*/, output];
545
- case 4:
546
- e_10 = _a.sent();
547
- log.error(tag, "e: ", e_10);
548
- throw e_10;
549
- case 5: return [2 /*return*/];
550
- }
551
- });
552
- });
553
- };
554
- var get_balance = function (address) {
555
- return __awaiter(this, void 0, void 0, function () {
556
- var tag, output, accountInfo, i, entry, e_11, e_12;
557
- var _a;
558
- return __generator(this, function (_b) {
559
- switch (_b.label) {
560
- case 0:
561
- tag = TAG + " | get_balance | ";
562
- _b.label = 1;
563
- case 1:
564
- _b.trys.push([1, 6, , 7]);
565
- output = 0;
566
- _b.label = 2;
567
- case 2:
568
- _b.trys.push([2, 4, , 5]);
569
- return [4 /*yield*/, axios({ method: 'GET', url: URL_THORNODE + '/bank/balances/' + address })];
570
- case 3:
571
- accountInfo = _b.sent();
572
- log.info(tag, "accountInfo: ", accountInfo.data);
573
- //
574
- if ((_a = accountInfo.data) === null || _a === void 0 ? void 0 : _a.result) {
575
- for (i = 0; i < accountInfo.data.result.length; i++) {
576
- entry = accountInfo.data.result[i];
577
- if (entry.denom === 'cacao') {
578
- output = entry.amount;
579
- }
580
- }
581
- }
582
- output = output / BASE_THOR;
583
- return [3 /*break*/, 5];
584
- case 4:
585
- e_11 = _b.sent();
586
- return [3 /*break*/, 5];
587
- case 5: return [2 /*return*/, output];
588
- case 6:
589
- e_12 = _b.sent();
590
- log.error(tag, "e: ", e_12);
591
- throw e_12;
592
- case 7: return [2 /*return*/];
593
- }
594
- });
595
- });
596
- };
597
- var get_balances = function (address) {
598
- return __awaiter(this, void 0, void 0, function () {
599
- var tag, output, accountInfo, i, entry, e_13, e_14;
600
- var _a;
601
- return __generator(this, function (_b) {
602
- switch (_b.label) {
603
- case 0:
604
- tag = TAG + " | get_balances | ";
605
- _b.label = 1;
606
- case 1:
607
- _b.trys.push([1, 6, , 7]);
608
- output = [];
609
- _b.label = 2;
610
417
  case 2:
611
- _b.trys.push([2, 4, , 5]);
612
- return [4 /*yield*/, axios({ method: 'GET', url: URL_THORNODE + '/bank/balances/' + address })];
418
+ result = _a.sent();
419
+ return [2 /*return*/, result.data];
613
420
  case 3:
614
- accountInfo = _b.sent();
615
- log.info(tag, "accountInfo: ", accountInfo.data);
616
- //
617
- if ((_a = accountInfo.data) === null || _a === void 0 ? void 0 : _a.result) {
618
- for (i = 0; i < accountInfo.data.result.length; i++) {
619
- entry = accountInfo.data.result[i];
620
- if (entry.denom === 'cacao') {
621
- output.push({
622
- denom: entry.denom,
623
- amountBase: entry.amount,
624
- amount: entry.amount / 10000000000,
625
- decimals: 10
626
- });
627
- }
628
- if (entry.denom === 'maya') {
629
- output.push({
630
- denom: entry.denom,
631
- amountBase: entry.amount,
632
- amount: entry.amount / 10000,
633
- decimals: 4
634
- });
635
- }
636
- }
637
- }
638
- return [3 /*break*/, 5];
639
- case 4:
640
- e_13 = _b.sent();
641
- return [3 /*break*/, 5];
642
- case 5: return [2 /*return*/, output];
643
- case 6:
644
- e_14 = _b.sent();
645
- log.error(tag, "e: ", e_14);
646
- throw e_14;
647
- case 7: return [2 /*return*/];
421
+ e_8 = _a.sent();
422
+ log.error(tag, "Error:", e_8.message);
423
+ throw e_8;
424
+ case 4: return [2 /*return*/];
648
425
  }
649
426
  });
650
427
  });
651
428
  };
652
- var get_node_info_verbose = function () {
429
+ var get_pool_addresses = function () {
653
430
  return __awaiter(this, void 0, void 0, function () {
654
- var tag, output, syncInfo, nodeInfo, lastBlock, e_15;
431
+ var tag;
655
432
  return __generator(this, function (_a) {
656
- switch (_a.label) {
657
- case 0:
658
- tag = TAG + " | get_node_info | ";
659
- _a.label = 1;
660
- case 1:
661
- _a.trys.push([1, 5, , 6]);
662
- output = {};
663
- return [4 /*yield*/, axios({ method: 'GET', url: URL_THORNODE + '/syncing' })];
664
- case 2:
665
- syncInfo = _a.sent();
666
- log.debug(tag, "syncInfo: ", syncInfo.data);
667
- output.isSyncing = syncInfo.data;
668
- return [4 /*yield*/, axios({ method: 'GET', url: URL_THORNODE + '/node_info' })];
669
- case 3:
670
- nodeInfo = _a.sent();
671
- log.debug(tag, "nodeInfo: ", nodeInfo.data);
672
- output = nodeInfo.data;
673
- return [4 /*yield*/, axios({ method: 'GET', url: URL_THORNODE + '/blocks/latest' })];
674
- case 4:
675
- lastBlock = _a.sent();
676
- log.debug(tag, "lastBlock: ", lastBlock.data);
677
- //let height
678
- output.height = lastBlock.data.block.header.height;
679
- return [2 /*return*/, output];
680
- case 5:
681
- e_15 = _a.sent();
682
- log.error(tag, "e: ", e_15);
683
- throw e_15;
684
- case 6: return [2 /*return*/];
433
+ tag = TAG + " | get_pool_addresses | ";
434
+ try {
435
+ // This endpoint might not be available, would need node access
436
+ log.warn(tag, "Pool addresses endpoint may require direct node access");
437
+ throw new Error("Pool addresses not available in Unchained API");
438
+ }
439
+ catch (e) {
440
+ log.error(tag, "Error:", e.message);
441
+ throw e;
685
442
  }
443
+ return [2 /*return*/];
686
444
  });
687
445
  });
688
446
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pioneer-platform/maya-network",
3
- "version": "8.11.0",
3
+ "version": "8.12.0",
4
4
  "main": "./lib/index.js",
5
5
  "types": "./lib/index.d.ts",
6
6
  "scripts": {