@pioneer-platform/pioneer-sdk 4.20.12 → 4.20.15

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/dist/index.cjs CHANGED
@@ -1754,10 +1754,19 @@ var extractChainIdFromNetworkId = (networkId) => {
1754
1754
  }
1755
1755
  return parseInt(id);
1756
1756
  };
1757
- async function fetchEthPriceInUsd() {
1758
- const response = await fetch("https://api.coingecko.com/api/v3/simple/price?ids=ethereum&vs_currencies=usd");
1759
- const data = await response.json();
1760
- return data.ethereum.usd;
1757
+ async function fetchEthPriceInUsd(pioneer, networkId) {
1758
+ const gasCaip = `${networkId}/slip44:60`;
1759
+ try {
1760
+ const marketInfo = await pioneer.GetMarketInfo([gasCaip]);
1761
+ if (marketInfo?.data && marketInfo.data.length > 0 && marketInfo.data[0] > 0) {
1762
+ return marketInfo.data[0];
1763
+ }
1764
+ console.warn("ETH price not available from Pioneer API, using fallback");
1765
+ return 0;
1766
+ } catch (error) {
1767
+ console.error("Error fetching ETH price from Pioneer API:", error);
1768
+ return 0;
1769
+ }
1761
1770
  }
1762
1771
  var extractContractAddressFromCaip = (caip) => {
1763
1772
  const parts = caip.split("/");
@@ -1784,14 +1793,18 @@ var encodeTransferData = (toAddress, amountWei) => {
1784
1793
  const data = "0x" + functionSignature + toAddressPadded + amountPadded;
1785
1794
  return data;
1786
1795
  };
1787
- async function fetchTokenPriceInUsd(contractAddress) {
1788
- const response = await fetch(`https://api.coingecko.com/api/v3/simple/token_price/ethereum?contract_addresses=${contractAddress}&vs_currencies=usd`);
1789
- const data = await response.json();
1790
- const price = data[contractAddress.toLowerCase()]?.usd;
1791
- if (!price) {
1792
- throw new Error("Failed to fetch token price");
1796
+ async function fetchTokenPriceInUsd(pioneer, caip) {
1797
+ try {
1798
+ const marketInfo = await pioneer.GetMarketInfo([caip]);
1799
+ if (marketInfo?.data && marketInfo.data.length > 0 && marketInfo.data[0] > 0) {
1800
+ return marketInfo.data[0];
1801
+ }
1802
+ console.warn(`Token price not available from Pioneer API for ${caip}, using 0`);
1803
+ return 0;
1804
+ } catch (error) {
1805
+ console.error(`Error fetching token price from Pioneer API for ${caip}:`, error);
1806
+ return 0;
1793
1807
  }
1794
- return price;
1795
1808
  }
1796
1809
  async function createUnsignedEvmTx(caip, to, amount, memo, pubkeys, pioneer, pubkeyContext, isMax, feeLevel = 5) {
1797
1810
  const tag5 = TAG + " | createUnsignedEvmTx | ";
@@ -2022,11 +2035,20 @@ async function createUnsignedEvmTx(caip, to, amount, memo, pubkeys, pioneer, pub
2022
2035
  }
2023
2036
  case "erc20": {
2024
2037
  const contractAddress = extractContractAddressFromCaip(caip);
2025
- let tokenDecimals = 18;
2026
- const contractLower = contractAddress.toLowerCase();
2027
- if (contractLower === "0xdac17f958d2ee523a2206206994597c13d831ec7" || contractLower === "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48" || contractLower === "0x4fabb145d64652a948d72533023f6e7a623c7c53" || contractLower === "0x8e870d67f660d95d5be530380d0ec0bd388289e1") {
2028
- tokenDecimals = 6;
2029
- console.log(tag5, "Using 6 decimals for stablecoin:", contractAddress);
2038
+ console.log(tag5, "Fetching token decimals from contract:", contractAddress, "on network:", networkId);
2039
+ let tokenDecimals;
2040
+ try {
2041
+ console.log(tag5, "Fetching token decimals via pioneer-server API for", contractAddress, "on", networkId);
2042
+ const decimalsResponse = await pioneer.GetTokenDecimals({
2043
+ networkId,
2044
+ contractAddress
2045
+ });
2046
+ tokenDecimals = Number(decimalsResponse.data.decimals);
2047
+ console.log(tag5, "✅ Fetched decimals from pioneer-server:", tokenDecimals);
2048
+ } catch (error) {
2049
+ console.error(tag5, "Failed to fetch token decimals from pioneer-server:", error);
2050
+ console.warn(tag5, "⚠️ FALLBACK: Using default 18 decimals - THIS MAY BE INCORRECT!");
2051
+ tokenDecimals = 18;
2030
2052
  }
2031
2053
  const tokenMultiplier = 10n ** BigInt(tokenDecimals);
2032
2054
  let gasLimit = BigInt(1e5);
@@ -2057,9 +2079,9 @@ async function createUnsignedEvmTx(caip, to, amount, memo, pubkeys, pioneer, pub
2057
2079
  throw new Error("Insufficient ETH balance to cover gas fees");
2058
2080
  }
2059
2081
  const data = encodeTransferData(to, amountWei);
2060
- const ethPriceInUsd = await fetchEthPriceInUsd();
2082
+ const ethPriceInUsd = await fetchEthPriceInUsd(pioneer, networkId);
2061
2083
  const gasFeeUsd = Number(gasFee) / 1000000000000000000 * ethPriceInUsd;
2062
- const tokenPriceInUsd = await fetchTokenPriceInUsd(contractAddress);
2084
+ const tokenPriceInUsd = await fetchTokenPriceInUsd(pioneer, caip);
2063
2085
  const amountUsd = Number(amountWei) / Number(tokenMultiplier) * tokenPriceInUsd;
2064
2086
  unsignedTx = {
2065
2087
  chainId,
@@ -2364,12 +2386,14 @@ async function createUnsignedTendermintTx(caip, type, amount, memo, pubkeys, pio
2364
2386
  let balanceInfo = await pioneer.GetPubkeyBalance({ asset: chain, pubkey: fromAddress });
2365
2387
  console.log(tag5, `\uD83D\uDCB0 balanceInfo:`, balanceInfo);
2366
2388
  let account_number, sequence;
2367
- if (networkId === "cosmos:cosmoshub-4" || networkId === "cosmos:osmosis-1") {
2389
+ if (accountInfo.account) {
2368
2390
  account_number = accountInfo.account.account_number || "0";
2369
2391
  sequence = accountInfo.account.sequence || "0";
2370
- } else if (networkId === "cosmos:thorchain-mainnet-v1" || networkId === "cosmos:mayachain-mainnet-v1") {
2392
+ } else if (accountInfo.result?.value) {
2371
2393
  account_number = accountInfo.result.value.account_number || "0";
2372
2394
  sequence = accountInfo.result.value.sequence || "0";
2395
+ } else {
2396
+ throw new Error(`Unexpected account info format for ${networkId}: ${JSON.stringify(accountInfo)}`);
2373
2397
  }
2374
2398
  console.log(tag5, `\uD83D\uDCCA Extracted account_number: ${account_number}, sequence: ${sequence}`);
2375
2399
  if (account_number === "0" || account_number === 0) {
@@ -4118,7 +4142,7 @@ class SDK {
4118
4142
  this.status = "preInit";
4119
4143
  this.appName = config.appName || "unknown app";
4120
4144
  this.appIcon = config.appIcon || "https://pioneers.dev/coins/keepkey.png";
4121
- this.spec = spec || config.spec || "https://pioneers.dev/spec/swagger";
4145
+ this.spec = spec || config.spec || "https://api.keepkey.info/spec/swagger";
4122
4146
  this.wss = config.wss || "wss://pioneers.dev";
4123
4147
  this.assets = import_pioneer_discovery2.assetData;
4124
4148
  this.assetsMap = new Map;
package/dist/index.es.js CHANGED
@@ -1930,10 +1930,19 @@ var extractChainIdFromNetworkId = (networkId) => {
1930
1930
  }
1931
1931
  return parseInt(id);
1932
1932
  };
1933
- async function fetchEthPriceInUsd() {
1934
- const response = await fetch("https://api.coingecko.com/api/v3/simple/price?ids=ethereum&vs_currencies=usd");
1935
- const data = await response.json();
1936
- return data.ethereum.usd;
1933
+ async function fetchEthPriceInUsd(pioneer, networkId) {
1934
+ const gasCaip = `${networkId}/slip44:60`;
1935
+ try {
1936
+ const marketInfo = await pioneer.GetMarketInfo([gasCaip]);
1937
+ if (marketInfo?.data && marketInfo.data.length > 0 && marketInfo.data[0] > 0) {
1938
+ return marketInfo.data[0];
1939
+ }
1940
+ console.warn("ETH price not available from Pioneer API, using fallback");
1941
+ return 0;
1942
+ } catch (error) {
1943
+ console.error("Error fetching ETH price from Pioneer API:", error);
1944
+ return 0;
1945
+ }
1937
1946
  }
1938
1947
  var extractContractAddressFromCaip = (caip) => {
1939
1948
  const parts = caip.split("/");
@@ -1960,14 +1969,18 @@ var encodeTransferData = (toAddress, amountWei) => {
1960
1969
  const data = "0x" + functionSignature + toAddressPadded + amountPadded;
1961
1970
  return data;
1962
1971
  };
1963
- async function fetchTokenPriceInUsd(contractAddress) {
1964
- const response = await fetch(`https://api.coingecko.com/api/v3/simple/token_price/ethereum?contract_addresses=${contractAddress}&vs_currencies=usd`);
1965
- const data = await response.json();
1966
- const price = data[contractAddress.toLowerCase()]?.usd;
1967
- if (!price) {
1968
- throw new Error("Failed to fetch token price");
1972
+ async function fetchTokenPriceInUsd(pioneer, caip) {
1973
+ try {
1974
+ const marketInfo = await pioneer.GetMarketInfo([caip]);
1975
+ if (marketInfo?.data && marketInfo.data.length > 0 && marketInfo.data[0] > 0) {
1976
+ return marketInfo.data[0];
1977
+ }
1978
+ console.warn(`Token price not available from Pioneer API for ${caip}, using 0`);
1979
+ return 0;
1980
+ } catch (error) {
1981
+ console.error(`Error fetching token price from Pioneer API for ${caip}:`, error);
1982
+ return 0;
1969
1983
  }
1970
- return price;
1971
1984
  }
1972
1985
  async function createUnsignedEvmTx(caip, to, amount, memo, pubkeys, pioneer, pubkeyContext, isMax, feeLevel = 5) {
1973
1986
  const tag5 = TAG + " | createUnsignedEvmTx | ";
@@ -2198,11 +2211,20 @@ async function createUnsignedEvmTx(caip, to, amount, memo, pubkeys, pioneer, pub
2198
2211
  }
2199
2212
  case "erc20": {
2200
2213
  const contractAddress = extractContractAddressFromCaip(caip);
2201
- let tokenDecimals = 18;
2202
- const contractLower = contractAddress.toLowerCase();
2203
- if (contractLower === "0xdac17f958d2ee523a2206206994597c13d831ec7" || contractLower === "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48" || contractLower === "0x4fabb145d64652a948d72533023f6e7a623c7c53" || contractLower === "0x8e870d67f660d95d5be530380d0ec0bd388289e1") {
2204
- tokenDecimals = 6;
2205
- console.log(tag5, "Using 6 decimals for stablecoin:", contractAddress);
2214
+ console.log(tag5, "Fetching token decimals from contract:", contractAddress, "on network:", networkId);
2215
+ let tokenDecimals;
2216
+ try {
2217
+ console.log(tag5, "Fetching token decimals via pioneer-server API for", contractAddress, "on", networkId);
2218
+ const decimalsResponse = await pioneer.GetTokenDecimals({
2219
+ networkId,
2220
+ contractAddress
2221
+ });
2222
+ tokenDecimals = Number(decimalsResponse.data.decimals);
2223
+ console.log(tag5, "✅ Fetched decimals from pioneer-server:", tokenDecimals);
2224
+ } catch (error) {
2225
+ console.error(tag5, "Failed to fetch token decimals from pioneer-server:", error);
2226
+ console.warn(tag5, "⚠️ FALLBACK: Using default 18 decimals - THIS MAY BE INCORRECT!");
2227
+ tokenDecimals = 18;
2206
2228
  }
2207
2229
  const tokenMultiplier = 10n ** BigInt(tokenDecimals);
2208
2230
  let gasLimit = BigInt(1e5);
@@ -2233,9 +2255,9 @@ async function createUnsignedEvmTx(caip, to, amount, memo, pubkeys, pioneer, pub
2233
2255
  throw new Error("Insufficient ETH balance to cover gas fees");
2234
2256
  }
2235
2257
  const data = encodeTransferData(to, amountWei);
2236
- const ethPriceInUsd = await fetchEthPriceInUsd();
2258
+ const ethPriceInUsd = await fetchEthPriceInUsd(pioneer, networkId);
2237
2259
  const gasFeeUsd = Number(gasFee) / 1000000000000000000 * ethPriceInUsd;
2238
- const tokenPriceInUsd = await fetchTokenPriceInUsd(contractAddress);
2260
+ const tokenPriceInUsd = await fetchTokenPriceInUsd(pioneer, caip);
2239
2261
  const amountUsd = Number(amountWei) / Number(tokenMultiplier) * tokenPriceInUsd;
2240
2262
  unsignedTx = {
2241
2263
  chainId,
@@ -2540,12 +2562,14 @@ async function createUnsignedTendermintTx(caip, type, amount, memo, pubkeys, pio
2540
2562
  let balanceInfo = await pioneer.GetPubkeyBalance({ asset: chain, pubkey: fromAddress });
2541
2563
  console.log(tag5, `\uD83D\uDCB0 balanceInfo:`, balanceInfo);
2542
2564
  let account_number, sequence;
2543
- if (networkId === "cosmos:cosmoshub-4" || networkId === "cosmos:osmosis-1") {
2565
+ if (accountInfo.account) {
2544
2566
  account_number = accountInfo.account.account_number || "0";
2545
2567
  sequence = accountInfo.account.sequence || "0";
2546
- } else if (networkId === "cosmos:thorchain-mainnet-v1" || networkId === "cosmos:mayachain-mainnet-v1") {
2568
+ } else if (accountInfo.result?.value) {
2547
2569
  account_number = accountInfo.result.value.account_number || "0";
2548
2570
  sequence = accountInfo.result.value.sequence || "0";
2571
+ } else {
2572
+ throw new Error(`Unexpected account info format for ${networkId}: ${JSON.stringify(accountInfo)}`);
2549
2573
  }
2550
2574
  console.log(tag5, `\uD83D\uDCCA Extracted account_number: ${account_number}, sequence: ${sequence}`);
2551
2575
  if (account_number === "0" || account_number === 0) {
@@ -4294,7 +4318,7 @@ class SDK {
4294
4318
  this.status = "preInit";
4295
4319
  this.appName = config.appName || "unknown app";
4296
4320
  this.appIcon = config.appIcon || "https://pioneers.dev/coins/keepkey.png";
4297
- this.spec = spec || config.spec || "https://pioneers.dev/spec/swagger";
4321
+ this.spec = spec || config.spec || "https://api.keepkey.info/spec/swagger";
4298
4322
  this.wss = config.wss || "wss://pioneers.dev";
4299
4323
  this.assets = assetData2;
4300
4324
  this.assetsMap = new Map;
package/dist/index.js CHANGED
@@ -1930,10 +1930,19 @@ var extractChainIdFromNetworkId = (networkId) => {
1930
1930
  }
1931
1931
  return parseInt(id);
1932
1932
  };
1933
- async function fetchEthPriceInUsd() {
1934
- const response = await fetch("https://api.coingecko.com/api/v3/simple/price?ids=ethereum&vs_currencies=usd");
1935
- const data = await response.json();
1936
- return data.ethereum.usd;
1933
+ async function fetchEthPriceInUsd(pioneer, networkId) {
1934
+ const gasCaip = `${networkId}/slip44:60`;
1935
+ try {
1936
+ const marketInfo = await pioneer.GetMarketInfo([gasCaip]);
1937
+ if (marketInfo?.data && marketInfo.data.length > 0 && marketInfo.data[0] > 0) {
1938
+ return marketInfo.data[0];
1939
+ }
1940
+ console.warn("ETH price not available from Pioneer API, using fallback");
1941
+ return 0;
1942
+ } catch (error) {
1943
+ console.error("Error fetching ETH price from Pioneer API:", error);
1944
+ return 0;
1945
+ }
1937
1946
  }
1938
1947
  var extractContractAddressFromCaip = (caip) => {
1939
1948
  const parts = caip.split("/");
@@ -1960,14 +1969,18 @@ var encodeTransferData = (toAddress, amountWei) => {
1960
1969
  const data = "0x" + functionSignature + toAddressPadded + amountPadded;
1961
1970
  return data;
1962
1971
  };
1963
- async function fetchTokenPriceInUsd(contractAddress) {
1964
- const response = await fetch(`https://api.coingecko.com/api/v3/simple/token_price/ethereum?contract_addresses=${contractAddress}&vs_currencies=usd`);
1965
- const data = await response.json();
1966
- const price = data[contractAddress.toLowerCase()]?.usd;
1967
- if (!price) {
1968
- throw new Error("Failed to fetch token price");
1972
+ async function fetchTokenPriceInUsd(pioneer, caip) {
1973
+ try {
1974
+ const marketInfo = await pioneer.GetMarketInfo([caip]);
1975
+ if (marketInfo?.data && marketInfo.data.length > 0 && marketInfo.data[0] > 0) {
1976
+ return marketInfo.data[0];
1977
+ }
1978
+ console.warn(`Token price not available from Pioneer API for ${caip}, using 0`);
1979
+ return 0;
1980
+ } catch (error) {
1981
+ console.error(`Error fetching token price from Pioneer API for ${caip}:`, error);
1982
+ return 0;
1969
1983
  }
1970
- return price;
1971
1984
  }
1972
1985
  async function createUnsignedEvmTx(caip, to, amount, memo, pubkeys, pioneer, pubkeyContext, isMax, feeLevel = 5) {
1973
1986
  const tag5 = TAG + " | createUnsignedEvmTx | ";
@@ -2198,11 +2211,20 @@ async function createUnsignedEvmTx(caip, to, amount, memo, pubkeys, pioneer, pub
2198
2211
  }
2199
2212
  case "erc20": {
2200
2213
  const contractAddress = extractContractAddressFromCaip(caip);
2201
- let tokenDecimals = 18;
2202
- const contractLower = contractAddress.toLowerCase();
2203
- if (contractLower === "0xdac17f958d2ee523a2206206994597c13d831ec7" || contractLower === "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48" || contractLower === "0x4fabb145d64652a948d72533023f6e7a623c7c53" || contractLower === "0x8e870d67f660d95d5be530380d0ec0bd388289e1") {
2204
- tokenDecimals = 6;
2205
- console.log(tag5, "Using 6 decimals for stablecoin:", contractAddress);
2214
+ console.log(tag5, "Fetching token decimals from contract:", contractAddress, "on network:", networkId);
2215
+ let tokenDecimals;
2216
+ try {
2217
+ console.log(tag5, "Fetching token decimals via pioneer-server API for", contractAddress, "on", networkId);
2218
+ const decimalsResponse = await pioneer.GetTokenDecimals({
2219
+ networkId,
2220
+ contractAddress
2221
+ });
2222
+ tokenDecimals = Number(decimalsResponse.data.decimals);
2223
+ console.log(tag5, "✅ Fetched decimals from pioneer-server:", tokenDecimals);
2224
+ } catch (error) {
2225
+ console.error(tag5, "Failed to fetch token decimals from pioneer-server:", error);
2226
+ console.warn(tag5, "⚠️ FALLBACK: Using default 18 decimals - THIS MAY BE INCORRECT!");
2227
+ tokenDecimals = 18;
2206
2228
  }
2207
2229
  const tokenMultiplier = 10n ** BigInt(tokenDecimals);
2208
2230
  let gasLimit = BigInt(1e5);
@@ -2233,9 +2255,9 @@ async function createUnsignedEvmTx(caip, to, amount, memo, pubkeys, pioneer, pub
2233
2255
  throw new Error("Insufficient ETH balance to cover gas fees");
2234
2256
  }
2235
2257
  const data = encodeTransferData(to, amountWei);
2236
- const ethPriceInUsd = await fetchEthPriceInUsd();
2258
+ const ethPriceInUsd = await fetchEthPriceInUsd(pioneer, networkId);
2237
2259
  const gasFeeUsd = Number(gasFee) / 1000000000000000000 * ethPriceInUsd;
2238
- const tokenPriceInUsd = await fetchTokenPriceInUsd(contractAddress);
2260
+ const tokenPriceInUsd = await fetchTokenPriceInUsd(pioneer, caip);
2239
2261
  const amountUsd = Number(amountWei) / Number(tokenMultiplier) * tokenPriceInUsd;
2240
2262
  unsignedTx = {
2241
2263
  chainId,
@@ -2540,12 +2562,14 @@ async function createUnsignedTendermintTx(caip, type, amount, memo, pubkeys, pio
2540
2562
  let balanceInfo = await pioneer.GetPubkeyBalance({ asset: chain, pubkey: fromAddress });
2541
2563
  console.log(tag5, `\uD83D\uDCB0 balanceInfo:`, balanceInfo);
2542
2564
  let account_number, sequence;
2543
- if (networkId === "cosmos:cosmoshub-4" || networkId === "cosmos:osmosis-1") {
2565
+ if (accountInfo.account) {
2544
2566
  account_number = accountInfo.account.account_number || "0";
2545
2567
  sequence = accountInfo.account.sequence || "0";
2546
- } else if (networkId === "cosmos:thorchain-mainnet-v1" || networkId === "cosmos:mayachain-mainnet-v1") {
2568
+ } else if (accountInfo.result?.value) {
2547
2569
  account_number = accountInfo.result.value.account_number || "0";
2548
2570
  sequence = accountInfo.result.value.sequence || "0";
2571
+ } else {
2572
+ throw new Error(`Unexpected account info format for ${networkId}: ${JSON.stringify(accountInfo)}`);
2549
2573
  }
2550
2574
  console.log(tag5, `\uD83D\uDCCA Extracted account_number: ${account_number}, sequence: ${sequence}`);
2551
2575
  if (account_number === "0" || account_number === 0) {
@@ -4294,7 +4318,7 @@ class SDK {
4294
4318
  this.status = "preInit";
4295
4319
  this.appName = config.appName || "unknown app";
4296
4320
  this.appIcon = config.appIcon || "https://pioneers.dev/coins/keepkey.png";
4297
- this.spec = spec || config.spec || "https://pioneers.dev/spec/swagger";
4321
+ this.spec = spec || config.spec || "https://api.keepkey.info/spec/swagger";
4298
4322
  this.wss = config.wss || "wss://pioneers.dev";
4299
4323
  this.assets = assetData2;
4300
4324
  this.assetsMap = new Map;
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "author": "highlander",
3
3
  "name": "@pioneer-platform/pioneer-sdk",
4
- "version": "4.20.12",
4
+ "version": "4.20.15",
5
5
  "dependencies": {
6
6
  "@keepkey/keepkey-sdk": "^0.2.62",
7
7
  "@pioneer-platform/loggerdog": "^8.11.0",
8
8
  "@pioneer-platform/pioneer-caip": "^9.10.0",
9
- "@pioneer-platform/pioneer-client": "^9.10.4",
9
+ "@pioneer-platform/pioneer-client": "^9.10.5",
10
10
  "@pioneer-platform/pioneer-coins": "^9.11.0",
11
11
  "@pioneer-platform/pioneer-discovery": "^0.8.0",
12
12
  "@pioneer-platform/pioneer-events": "^8.11.0",
package/src/index.ts CHANGED
@@ -172,7 +172,7 @@ export class SDK {
172
172
  this.status = 'preInit';
173
173
  this.appName = config.appName || 'unknown app';
174
174
  this.appIcon = config.appIcon || 'https://pioneers.dev/coins/keepkey.png';
175
- this.spec = spec || config.spec || 'https://pioneers.dev/spec/swagger';
175
+ this.spec = spec || config.spec || 'https://api.keepkey.info/spec/swagger';
176
176
  this.wss = config.wss || 'wss://pioneers.dev';
177
177
  this.assets = assetData;
178
178
  this.assetsMap = new Map();
@@ -32,13 +32,24 @@ const extractChainIdFromNetworkId = (networkId) => {
32
32
  return parseInt(id);
33
33
  };
34
34
 
35
- // Fetch the current ETH price in USD from CoinGecko
36
- async function fetchEthPriceInUsd() {
37
- const response = await fetch(
38
- 'https://api.coingecko.com/api/v3/simple/price?ids=ethereum&vs_currencies=usd',
39
- );
40
- const data = await response.json();
41
- return data.ethereum.usd;
35
+ // Fetch the current ETH price in USD from Pioneer API
36
+ async function fetchEthPriceInUsd(pioneer: any, networkId: string) {
37
+ // Build CAIP for the native gas token based on networkId
38
+ // For EVM chains, the native gas asset uses slip44 format
39
+ const gasCaip = `${networkId}/slip44:60`; // ETH slip44 code
40
+
41
+ try {
42
+ const marketInfo = await pioneer.GetMarketInfo([gasCaip]);
43
+ if (marketInfo?.data && marketInfo.data.length > 0 && marketInfo.data[0] > 0) {
44
+ return marketInfo.data[0];
45
+ }
46
+ // Fallback if price not available
47
+ console.warn('ETH price not available from Pioneer API, using fallback');
48
+ return 0;
49
+ } catch (error) {
50
+ console.error('Error fetching ETH price from Pioneer API:', error);
51
+ return 0;
52
+ }
42
53
  }
43
54
 
44
55
  // Extract contract address from CAIP
@@ -75,19 +86,21 @@ const encodeTransferData = (toAddress, amountWei) => {
75
86
  return data;
76
87
  };
77
88
 
78
- //TODO use assetData here, this is horrible
79
- // Helper function to fetch token price in USD
80
- async function fetchTokenPriceInUsd(contractAddress) {
81
- // Use CoinGecko API to get token price by contract address
82
- const response = await fetch(
83
- `https://api.coingecko.com/api/v3/simple/token_price/ethereum?contract_addresses=${contractAddress}&vs_currencies=usd`,
84
- );
85
- const data = await response.json();
86
- const price = data[contractAddress.toLowerCase()]?.usd;
87
- if (!price) {
88
- throw new Error('Failed to fetch token price');
89
+ // Helper function to fetch token price in USD from Pioneer API
90
+ async function fetchTokenPriceInUsd(pioneer: any, caip: string) {
91
+ // Use the full CAIP string to get price from Pioneer API
92
+ try {
93
+ const marketInfo = await pioneer.GetMarketInfo([caip]);
94
+ if (marketInfo?.data && marketInfo.data.length > 0 && marketInfo.data[0] > 0) {
95
+ return marketInfo.data[0];
96
+ }
97
+ // Fallback if price not available
98
+ console.warn(`Token price not available from Pioneer API for ${caip}, using 0`);
99
+ return 0;
100
+ } catch (error) {
101
+ console.error(`Error fetching token price from Pioneer API for ${caip}:`, error);
102
+ return 0;
89
103
  }
90
- return price;
91
104
  }
92
105
 
93
106
  // Create an unsigned EVM transaction
@@ -455,26 +468,27 @@ export async function createUnsignedEvmTx(
455
468
  case 'erc20': {
456
469
  const contractAddress = extractContractAddressFromCaip(caip);
457
470
 
458
- // Get token decimals - CRITICAL for correct amount calculation
459
- // Common token decimals:
460
- // USDT: 6, USDC: 6, DAI: 18, WETH: 18, most others: 18
461
- let tokenDecimals = 18; // Default to 18 if not specified
462
-
463
- // Check for known stablecoins with 6 decimals
464
- const contractLower = contractAddress.toLowerCase();
465
- if (
466
- contractLower === '0xdac17f958d2ee523a2206206994597c13d831ec7' || // USDT on Ethereum
467
- contractLower === '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48' || // USDC on Ethereum
468
- contractLower === '0x4fabb145d64652a948d72533023f6e7a623c7c53' || // BUSD on Ethereum
469
- contractLower === '0x8e870d67f660d95d5be530380d0ec0bd388289e1'
470
- ) {
471
- // USDP on Ethereum
472
- tokenDecimals = 6;
473
- console.log(tag, 'Using 6 decimals for stablecoin:', contractAddress);
474
- }
471
+ // Get token decimals from contract - CRITICAL for correct amount calculation
472
+ // Fetch decimals from contract directly (handles all tokens on all chains)
473
+ console.log(tag, 'Fetching token decimals from contract:', contractAddress, 'on network:', networkId);
475
474
 
476
- // TODO: Fetch decimals from contract in the future:
477
- // const decimals = await getTokenDecimals(contractAddress, networkId);
475
+ let tokenDecimals: number;
476
+ try {
477
+ // Call pioneer-server API to get token decimals (server handles RPC calls)
478
+ console.log(tag, 'Fetching token decimals via pioneer-server API for', contractAddress, 'on', networkId);
479
+ const decimalsResponse = await pioneer.GetTokenDecimals({
480
+ networkId,
481
+ contractAddress,
482
+ });
483
+
484
+ tokenDecimals = Number(decimalsResponse.data.decimals);
485
+ console.log(tag, '✅ Fetched decimals from pioneer-server:', tokenDecimals);
486
+ } catch (error: any) {
487
+ console.error(tag, 'Failed to fetch token decimals from pioneer-server:', error);
488
+ // Fallback to 18 decimals as last resort (but log warning)
489
+ console.warn(tag, '⚠️ FALLBACK: Using default 18 decimals - THIS MAY BE INCORRECT!');
490
+ tokenDecimals = 18;
491
+ }
478
492
 
479
493
  // Use BigInt for precise decimal math (no float drift)
480
494
  const tokenMultiplier = 10n ** BigInt(tokenDecimals);
@@ -526,11 +540,11 @@ export async function createUnsignedEvmTx(
526
540
 
527
541
  const data = encodeTransferData(to, amountWei);
528
542
 
529
- const ethPriceInUsd = await fetchEthPriceInUsd();
543
+ const ethPriceInUsd = await fetchEthPriceInUsd(pioneer, networkId);
530
544
  const gasFeeUsd = (Number(gasFee) / 1e18) * ethPriceInUsd;
531
545
 
532
- // For token price, need to fetch from API
533
- const tokenPriceInUsd = await fetchTokenPriceInUsd(contractAddress);
546
+ // For token price, fetch from Pioneer API using the full CAIP
547
+ const tokenPriceInUsd = await fetchTokenPriceInUsd(pioneer, caip);
534
548
  // Use the correct decimals for USD calculation
535
549
  const amountUsd = (Number(amountWei) / Number(tokenMultiplier)) * tokenPriceInUsd;
536
550
 
@@ -73,15 +73,19 @@ export async function createUnsignedTendermintTx(
73
73
  console.log(tag, `💰 balanceInfo:`, balanceInfo);
74
74
 
75
75
  let account_number, sequence;
76
- if (networkId === 'cosmos:cosmoshub-4' || networkId === 'cosmos:osmosis-1') {
76
+
77
+ // Handle both old (result.value) and new (account) API formats
78
+ // Thorchain upgraded to Cosmos SDK v0.47+ format, similar to Cosmoshub/Osmosis
79
+ if (accountInfo.account) {
80
+ // New format (Cosmos SDK v0.47+): used by all chains now
77
81
  account_number = accountInfo.account.account_number || '0';
78
82
  sequence = accountInfo.account.sequence || '0';
79
- } else if (
80
- networkId === 'cosmos:thorchain-mainnet-v1' ||
81
- networkId === 'cosmos:mayachain-mainnet-v1'
82
- ) {
83
+ } else if (accountInfo.result?.value) {
84
+ // Old format (Cosmos SDK v0.45): legacy fallback
83
85
  account_number = accountInfo.result.value.account_number || '0';
84
86
  sequence = accountInfo.result.value.sequence || '0';
87
+ } else {
88
+ throw new Error(`Unexpected account info format for ${networkId}: ${JSON.stringify(accountInfo)}`);
85
89
  }
86
90
 
87
91
  console.log(tag, `📊 Extracted account_number: ${account_number}, sequence: ${sequence}`);