@pioneer-platform/maya-network 8.13.6 → 8.13.7
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 +6 -0
- package/MAYA_DECIMAL_FIX.md +136 -0
- package/lib/index.js +24 -5
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
# MAYA Decimal Fix Summary
|
|
2
|
+
|
|
3
|
+
## Problem Identified
|
|
4
|
+
|
|
5
|
+
MAYA token transfers were failing with "insufficient funds" error even when balance appeared sufficient. After diagnostic analysis, we discovered the root cause was **incorrect decimal handling**.
|
|
6
|
+
|
|
7
|
+
## Root Cause
|
|
8
|
+
|
|
9
|
+
**MAYA token was configured with 8 decimals instead of 4 decimals**, causing amount calculations to be off by 10,000x.
|
|
10
|
+
|
|
11
|
+
### Evidence from Successful Transaction
|
|
12
|
+
|
|
13
|
+
Transaction hash: `AE8DE76212A977141C971CF9D85598C946C0E7D84B634A7D8750C1C428EDDAE1`
|
|
14
|
+
|
|
15
|
+
- **Spendable balance**: 4104 base units = 0.4104 MAYA (at 4 decimals)
|
|
16
|
+
- **Failed attempt**: 10,000 base units (exceeded balance)
|
|
17
|
+
- **Successful attempt**: 1,000 base units (0.1 MAYA)
|
|
18
|
+
|
|
19
|
+
## Correct Decimal Configuration
|
|
20
|
+
|
|
21
|
+
Based on network behavior and successful transactions:
|
|
22
|
+
|
|
23
|
+
| Asset | Decimals | Base Unit Formula | Example |
|
|
24
|
+
|--------|----------|--------------------------------------|----------------------|
|
|
25
|
+
| CACAO | 10 | 1 CACAO = 10,000,000,000 base units | Native gas token |
|
|
26
|
+
| MAYA | 4 | 1 MAYA = 10,000 base units | Governance token |
|
|
27
|
+
|
|
28
|
+
## Changes Made
|
|
29
|
+
|
|
30
|
+
### 1. pioneer-discovery (`generatedAssetData.json`)
|
|
31
|
+
|
|
32
|
+
**File**: `/modules/pioneer/pioneer-discovery/src/generatedAssetData.json`
|
|
33
|
+
|
|
34
|
+
```diff
|
|
35
|
+
"cosmos:mayachain-mainnet-v1/denom:maya": {
|
|
36
|
+
...
|
|
37
|
+
- "precision": 8,
|
|
38
|
+
- "decimals": 8,
|
|
39
|
+
+ "precision": 4,
|
|
40
|
+
+ "decimals": 4,
|
|
41
|
+
...
|
|
42
|
+
}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### 2. pioneer-sdk (`createUnsignedTendermintTx.ts`)
|
|
46
|
+
|
|
47
|
+
**File**: `/modules/pioneer/pioneer-sdk/src/txbuilder/createUnsignedTendermintTx.ts`
|
|
48
|
+
|
|
49
|
+
**Before** (lines 69-87):
|
|
50
|
+
```typescript
|
|
51
|
+
case 'cosmos:mayachain-mainnet-v1': {
|
|
52
|
+
let mayaAsset: string;
|
|
53
|
+
if (caip.includes('/denom:maya')) {
|
|
54
|
+
mayaAsset = 'maya';
|
|
55
|
+
} else if (caip.includes('/slip44:931')) {
|
|
56
|
+
mayaAsset = 'cacao';
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// BUG: Always used 1e10 for both MAYA and CACAO
|
|
60
|
+
if (isMax) {
|
|
61
|
+
const fee = Math.floor(fees[networkId] * 1e10);
|
|
62
|
+
amount = Math.max(0, Math.floor(balanceInfo.data * 1e10) - fee);
|
|
63
|
+
} else {
|
|
64
|
+
amount = Math.max(Math.floor(amount * 1e10), 0);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
**After** (corrected):
|
|
70
|
+
```typescript
|
|
71
|
+
case 'cosmos:mayachain-mainnet-v1': {
|
|
72
|
+
let mayaAsset: string;
|
|
73
|
+
let decimals: number;
|
|
74
|
+
|
|
75
|
+
if (caip.includes('/denom:maya')) {
|
|
76
|
+
mayaAsset = 'maya';
|
|
77
|
+
decimals = 4; // MAYA has 4 decimals
|
|
78
|
+
} else if (caip.includes('/slip44:931')) {
|
|
79
|
+
mayaAsset = 'cacao';
|
|
80
|
+
decimals = 10; // CACAO has 10 decimals
|
|
81
|
+
} else {
|
|
82
|
+
throw new Error(`Unsupported Maya chain CAIP: ${caip}`);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const decimalMultiplier = Math.pow(10, decimals);
|
|
86
|
+
|
|
87
|
+
if (isMax) {
|
|
88
|
+
const fee = Math.floor(fees[networkId] * 1e10); // Fee always in CACAO
|
|
89
|
+
amount = Math.max(0, Math.floor(balanceInfo.data * decimalMultiplier) - fee);
|
|
90
|
+
} else {
|
|
91
|
+
amount = Math.max(Math.floor(amount * decimalMultiplier), 0);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## Verification
|
|
97
|
+
|
|
98
|
+
### Diagnostic Results
|
|
99
|
+
|
|
100
|
+
The diagnostic script (`__tests__/diagnose-maya-transfers.js`) confirmed:
|
|
101
|
+
|
|
102
|
+
1. ✅ **Spendable balance**: 4104 base units (0.4104 MAYA at 4 decimals)
|
|
103
|
+
2. ✅ **Account type**: Standard base account (no vesting/locks)
|
|
104
|
+
3. ⚠️ **Bank params**: `default_send_enabled: false` (not blocking - proven by successful tx)
|
|
105
|
+
4. ✅ **Transaction success**: 1000 base units sent successfully
|
|
106
|
+
|
|
107
|
+
### Fee Behavior
|
|
108
|
+
|
|
109
|
+
From the successful transaction events:
|
|
110
|
+
- User specified: `fee.amount = "0"` for CACAO
|
|
111
|
+
- Chain auto-deducted: ~2.0 CACAO (1,800,000,000 + 200,000,000 base units)
|
|
112
|
+
- This is normal MayaChain behavior - fees are always in CACAO
|
|
113
|
+
|
|
114
|
+
## Build Status
|
|
115
|
+
|
|
116
|
+
✅ `pioneer-discovery` - Built successfully
|
|
117
|
+
✅ `pioneer-sdk` - Built successfully (ESM + CommonJS)
|
|
118
|
+
|
|
119
|
+
## Testing Recommendations
|
|
120
|
+
|
|
121
|
+
1. **Balance Display**: Verify UI shows 4104 base units as "0.4104 MAYA" (not "0.00004104 MAYA")
|
|
122
|
+
2. **Send Validation**: Pre-check spendable balance before allowing sends
|
|
123
|
+
3. **Fee Display**: Surface the auto-deducted CACAO fees (~2.0 CACAO per tx)
|
|
124
|
+
4. **Amount Input**: Ensure send form respects 4 decimal places for MAYA
|
|
125
|
+
|
|
126
|
+
## Files Modified
|
|
127
|
+
|
|
128
|
+
1. `/modules/pioneer/pioneer-discovery/src/generatedAssetData.json`
|
|
129
|
+
2. `/modules/pioneer/pioneer-sdk/src/txbuilder/createUnsignedTendermintTx.ts`
|
|
130
|
+
|
|
131
|
+
## Related Documentation
|
|
132
|
+
|
|
133
|
+
- MayaChain docs: https://docs.mayaprotocol.com/
|
|
134
|
+
- Maya explorer: https://www.mayascan.org/
|
|
135
|
+
- Network module README: `mayachain-network/README.md`
|
|
136
|
+
- Diagnostic script: `mayachain-network/__tests__/diagnose-maya-transfers.js`
|
package/lib/index.js
CHANGED
|
@@ -270,12 +270,31 @@ var get_account_info = function (address) {
|
|
|
270
270
|
log.error(tag, "All endpoints failed");
|
|
271
271
|
throw new Error("All endpoints failed for account info");
|
|
272
272
|
}
|
|
273
|
-
// Log all
|
|
274
|
-
log.info(tag, "
|
|
275
|
-
|
|
276
|
-
|
|
273
|
+
// Log all results for debugging
|
|
274
|
+
log.info(tag, "Results from all nodes:", successfulResults.map(function (r) {
|
|
275
|
+
return "".concat(r.source, ": seq=").concat(r.sequence, ", acct=").concat(r.account_number, ", coins=").concat(r.coins.length);
|
|
276
|
+
}).join(', '));
|
|
277
|
+
mostRecentAccount = successfulResults.reduce(function (best, current) {
|
|
278
|
+
// Parse account numbers
|
|
279
|
+
var currentAcctNum = parseInt(current.account_number);
|
|
280
|
+
var bestAcctNum = parseInt(best.account_number);
|
|
281
|
+
// Prefer non-zero account numbers
|
|
282
|
+
if (currentAcctNum > 0 && bestAcctNum === 0)
|
|
283
|
+
return current;
|
|
284
|
+
if (bestAcctNum > 0 && currentAcctNum === 0)
|
|
285
|
+
return best;
|
|
286
|
+
// Check for balance (coins array)
|
|
287
|
+
var currentHasBalance = current.coins.length > 0;
|
|
288
|
+
var bestHasBalance = best.coins.length > 0;
|
|
289
|
+
// Prefer sources with balance data
|
|
290
|
+
if (currentHasBalance && !bestHasBalance)
|
|
291
|
+
return current;
|
|
292
|
+
if (bestHasBalance && !currentHasBalance)
|
|
293
|
+
return best;
|
|
294
|
+
// Finally, use highest sequence number as tiebreaker
|
|
295
|
+
return current.sequence > best.sequence ? current : best;
|
|
277
296
|
});
|
|
278
|
-
log.info(tag, "Using account info from ".concat(mostRecentAccount.source, "
|
|
297
|
+
log.info(tag, "Using account info from ".concat(mostRecentAccount.source, " (seq=").concat(mostRecentAccount.sequence, ", acct=").concat(mostRecentAccount.account_number, ", coins=").concat(mostRecentAccount.coins.length, ")"));
|
|
279
298
|
cacaoCoin = mostRecentAccount.coins.find(function (coin) { return coin.denom === 'cacao'; });
|
|
280
299
|
cacaoBalance = (cacaoCoin === null || cacaoCoin === void 0 ? void 0 : cacaoCoin.amount) || '0';
|
|
281
300
|
// Return in expected format
|