@tomo-inc/chains-service 0.0.23 → 0.0.24

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.
Files changed (50) hide show
  1. package/dist/index.cjs +30 -23
  2. package/dist/index.d.cts +2 -0
  3. package/dist/index.d.ts +2 -0
  4. package/dist/index.js +31 -24
  5. package/package.json +2 -1
  6. package/project.json +1 -1
  7. package/src/__tests__/config.test.ts +46 -0
  8. package/src/__tests__/dogecoin-utils.test.ts +147 -0
  9. package/src/__tests__/evm-utils.test.ts +133 -0
  10. package/src/__tests__/index.test.ts +40 -0
  11. package/src/__tests__/services.test.ts +285 -0
  12. package/src/__tests__/solana-utils.test.ts +131 -0
  13. package/src/__tests__/utils.test.ts +52 -0
  14. package/src/__tests__/wallet.test.ts +350 -0
  15. package/src/api/__tests__/base.test.ts +146 -0
  16. package/src/api/__tests__/index.test.ts +51 -0
  17. package/src/api/__tests__/network.test.ts +153 -0
  18. package/src/api/__tests__/token.test.ts +231 -2
  19. package/src/api/__tests__/transaction.test.ts +121 -6
  20. package/src/api/__tests__/user.test.ts +237 -3
  21. package/src/api/__tests__/wallet.test.ts +174 -4
  22. package/src/api/network.ts +9 -1
  23. package/src/api/utils/__tests__/index.test.ts +91 -0
  24. package/src/api/utils/__tests__/signature.test.ts +124 -0
  25. package/src/api/utils/index.ts +6 -2
  26. package/src/base/__tests__/network.test.ts +119 -0
  27. package/src/base/__tests__/service.test.ts +68 -0
  28. package/src/base/__tests__/token.test.ts +123 -0
  29. package/src/base/__tests__/transaction.test.ts +210 -0
  30. package/src/config.ts +1 -1
  31. package/src/dogecoin/__tests__/base.test.ts +76 -0
  32. package/src/dogecoin/__tests__/rpc.test.ts +465 -0
  33. package/src/dogecoin/__tests__/service-extended.test.ts +420 -0
  34. package/src/dogecoin/__tests__/utils-doge.test.ts +244 -0
  35. package/src/dogecoin/__tests__/utils-extended.test.ts +323 -0
  36. package/src/dogecoin/base.ts +1 -0
  37. package/src/dogecoin/config.ts +2 -2
  38. package/src/dogecoin/rpc.ts +10 -1
  39. package/src/dogecoin/service.ts +9 -5
  40. package/src/evm/__tests__/rpc.test.ts +132 -0
  41. package/src/evm/__tests__/service.test.ts +535 -0
  42. package/src/evm/__tests__/utils.test.ts +170 -0
  43. package/src/evm/utils.ts +2 -2
  44. package/src/solana/__tests__/service.test.ts +425 -0
  45. package/src/solana/__tests__/utils.test.ts +937 -0
  46. package/src/solana/config.ts +1 -1
  47. package/src/solana/service.ts +2 -0
  48. package/src/solana/utils.ts +2 -16
  49. package/src/utils/index.ts +1 -1
  50. package/vitest.config.ts +13 -0
package/dist/index.cjs CHANGED
@@ -2925,9 +2925,12 @@ function generateSignature(config) {
2925
2925
  // src/api/utils/index.ts
2926
2926
  var formatJwtToken = (jwtToken) => `Bearer ${jwtToken}`;
2927
2927
  function signRequest(params, clientId, signParams) {
2928
+ if (!params.headers) {
2929
+ params.headers = {};
2930
+ }
2928
2931
  if (typeof signParams === "string") {
2929
2932
  const jwtToken = signParams;
2930
- Object.assign(params.headers ?? {}, {
2933
+ Object.assign(params.headers, {
2931
2934
  "client-id": clientId,
2932
2935
  Authorization: formatJwtToken(jwtToken)
2933
2936
  });
@@ -2942,7 +2945,7 @@ function signRequest(params, clientId, signParams) {
2942
2945
  apiSecret,
2943
2946
  salt
2944
2947
  });
2945
- Object.assign(params.headers ?? {}, {
2948
+ Object.assign(params.headers, {
2946
2949
  "X-APP-Key": apiKey,
2947
2950
  "X-Signature": signature,
2948
2951
  "X-Timestamp": timestamp,
@@ -3854,11 +3857,17 @@ var NetworkAPIs = class _NetworkAPIs extends BasePublicService {
3854
3857
  getCacheId(chainType) {
3855
3858
  return `tomo-${chainType}-currentChainId`;
3856
3859
  }
3860
+ /** Map ChainTypeEnum to network-data platformType where they differ */
3861
+ static platformTypeForChain = {
3862
+ [walletUtils.ChainTypeEnum.DOGECOIN]: "DOGE",
3863
+ [walletUtils.ChainTypeEnum.BITCOIN]: "BTC"
3864
+ };
3857
3865
  getAllNetworks(chainType) {
3858
3866
  if (chainType === "") {
3859
3867
  return this.chains;
3860
3868
  }
3861
- return this.chains.filter((chain) => chain.platformType === chainType.toUpperCase());
3869
+ const platformType = _NetworkAPIs.platformTypeForChain[chainType] ?? chainType.toUpperCase();
3870
+ return this.chains.filter((chain) => chain.platformType === platformType);
3862
3871
  }
3863
3872
  async getCurrentNetwork(chainType) {
3864
3873
  if (!walletUtils.SupportedChainTypes?.[chainType]) {
@@ -3968,15 +3977,16 @@ function fromBase64(base64) {
3968
3977
  return new Uint8Array(buffer);
3969
3978
  }
3970
3979
  function toBase58(data) {
3980
+ console.warn("toBase58:", data);
3971
3981
  throw new Error("toBase58 requires bs58 package. Install it: pnpm add bs58");
3972
3982
  }
3973
- var BaseConfig = walletUtils.SupportedChainTypes[walletUtils.ChainTypeEnum.DOGE];
3983
+ var BaseConfig = walletUtils.SupportedChainTypes[walletUtils.ChainTypeEnum.DOGECOIN];
3974
3984
  var BLOCK_CONFIRMATIONS = 1;
3975
3985
  var FEE_RATE_KB = 0.5;
3976
3986
  var DECIMALS = 1e8;
3977
3987
  var TRANSACTION_PAGE_SIZE = 10;
3978
3988
  var MYDOGE_BASE_URL = "https://api.mydoge.com";
3979
- var RPC_URL_TOMO = "https://wallet-pro.tomo.inc/rpc/v1/doge_coin";
3989
+ var RPC_URL_TOMO = "https://wallet-test.tomo.inc/rpc/v1/doge_coin";
3980
3990
  var RPC_URL = "https://api.bitcore.io/api/DOGE/mainnet";
3981
3991
  var RPC_TIMEOUT = 20 * 1e3;
3982
3992
  var TX_OVERHEAD = 10;
@@ -4567,11 +4577,7 @@ var DogecoinService = class _DogecoinService extends BaseService {
4567
4577
  gasLimitParam,
4568
4578
  addressList: [txData.from]
4569
4579
  };
4570
- const {
4571
- data: gasInfo,
4572
- success,
4573
- message
4574
- } = await this.transactions.queryGasInfo({
4580
+ const { data: gasInfo, success } = await this.transactions.queryGasInfo({
4575
4581
  chainType: this.chainType,
4576
4582
  params: queryGasParams
4577
4583
  });
@@ -4623,6 +4629,9 @@ var DogecoinService = class _DogecoinService extends BaseService {
4623
4629
  async signPsbt({ psbtHex, options }) {
4624
4630
  const psbtBase64 = toBase64(fromHex(psbtHex));
4625
4631
  const signedPsbt = await this.accountInfo.signTransaction(JSON.stringify({ psbtBase64 }));
4632
+ if (!options) {
4633
+ console.warn("not support options.");
4634
+ }
4626
4635
  if (!signedPsbt) {
4627
4636
  throw new Error("error psbtHex:" + psbtHex);
4628
4637
  }
@@ -4630,6 +4639,7 @@ var DogecoinService = class _DogecoinService extends BaseService {
4630
4639
  return signedRawTx;
4631
4640
  }
4632
4641
  async signPsbts({ psbtHexs, options }) {
4642
+ console.warn("signPsbsts:", psbtHexs, options);
4633
4643
  throw new Error("not implemented");
4634
4644
  }
4635
4645
  async requestTransaction(txData) {
@@ -4659,6 +4669,9 @@ var DogecoinService = class _DogecoinService extends BaseService {
4659
4669
  fee = 0,
4660
4670
  options
4661
4671
  }) {
4672
+ if (options) {
4673
+ console.warn("not support options");
4674
+ }
4662
4675
  if (fee <= 0) {
4663
4676
  throw new Error("fee is required");
4664
4677
  }
@@ -4753,7 +4766,7 @@ var TxTypes = /* @__PURE__ */ ((TxTypes2) => {
4753
4766
 
4754
4767
  // src/evm/utils.ts
4755
4768
  var isEvmChain = (network2) => {
4756
- return network2 && network2?.platformType === "EVM";
4769
+ return network2?.platformType === "EVM" || false;
4757
4770
  };
4758
4771
  var getAllTypeChainIds = ({ chainId, chainType }) => {
4759
4772
  if (viem.isHex(chainId)) {
@@ -4767,7 +4780,7 @@ var getAllTypeChainIds = ({ chainId, chainType }) => {
4767
4780
  }
4768
4781
  const chainIdHex = viem.toHex(Number(chainId));
4769
4782
  return {
4770
- chainId,
4783
+ chainId: String(chainId),
4771
4784
  chainIdHex,
4772
4785
  chainUid: `${chainType}:${chainId}`
4773
4786
  };
@@ -5081,7 +5094,7 @@ var EvmService = class _EvmService extends BaseService {
5081
5094
  }
5082
5095
  }
5083
5096
  };
5084
- var BaseConfig2 = walletUtils.SupportedChainTypes[walletUtils.ChainTypeEnum.SOL];
5097
+ var BaseConfig2 = walletUtils.SupportedChainTypes[walletUtils.ChainTypeEnum.SOLANA];
5085
5098
  var TOKEN_METADATA_PROGRAM_ID = "metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s";
5086
5099
  var MSG_PREFIX = "\xFFsolana offchain";
5087
5100
 
@@ -5120,15 +5133,7 @@ async function createLegacyTx({ from = "", to = "", amount = 0 }, connection) {
5120
5133
  transaction.lastValidBlockHeight = lastValidBlockHeight;
5121
5134
  return transaction;
5122
5135
  }
5123
- async function createTokenLegacyTransaction2({
5124
- from = "",
5125
- to = "",
5126
- amount = 0,
5127
- tokenAddress = "",
5128
- priorityFee = 0,
5129
- // microLamports (1 SOL = 1e6 microLamports)
5130
- decimals = 6
5131
- }, connection) {
5136
+ async function createTokenLegacyTransaction2({ from = "", to = "", amount = 0, tokenAddress = "", decimals = 6 }, connection) {
5132
5137
  try {
5133
5138
  const fromPubkey = new web3_js.PublicKey(from);
5134
5139
  const toPubkey = new web3_js.PublicKey(to);
@@ -5281,7 +5286,7 @@ var SolanaService = class _SolanaService extends BaseService {
5281
5286
  web3_js.VersionedTransaction.deserialize(hexBuffer);
5282
5287
  rawTx = hexBuffer;
5283
5288
  } catch (error) {
5284
- const base58Buffer = Buffer.from(toBase58());
5289
+ const base58Buffer = Buffer.from(toBase58(signedTx));
5285
5290
  web3_js.VersionedTransaction.deserialize(base58Buffer);
5286
5291
  rawTx = base58Buffer;
5287
5292
  }
@@ -5333,9 +5338,11 @@ var SolanaService = class _SolanaService extends BaseService {
5333
5338
  return signature;
5334
5339
  }
5335
5340
  async signAllTransactions({ rawTransactions }) {
5341
+ console.warn("signAllTransactions:", rawTransactions);
5336
5342
  throw new Error("no support");
5337
5343
  }
5338
5344
  async signAndSendAllTransactions({ rawTransactions }) {
5345
+ console.warn("signAndSendAllTransactions:", rawTransactions);
5339
5346
  throw new Error("no support");
5340
5347
  }
5341
5348
  async queryRent(params) {
package/dist/index.d.cts CHANGED
@@ -309,6 +309,8 @@ declare class NetworkAPIs extends BasePublicService {
309
309
  private constructor();
310
310
  static getInstance(apiBase: IPublicApiBaseConfig, tomoAppInfo: TomoAppInfo): NetworkAPIs;
311
311
  getCacheId(chainType: ChainTypeEnum | ""): string;
312
+ /** Map ChainTypeEnum to network-data platformType where they differ */
313
+ private static readonly platformTypeForChain;
312
314
  getAllNetworks(chainType: ChainTypeEnum | ""): any[];
313
315
  getCurrentNetwork(chainType: ChainTypeEnum): Promise<string>;
314
316
  setCurrentNetwork(chainType: ChainTypeEnum | "", chainId: string): Promise<void>;
package/dist/index.d.ts CHANGED
@@ -309,6 +309,8 @@ declare class NetworkAPIs extends BasePublicService {
309
309
  private constructor();
310
310
  static getInstance(apiBase: IPublicApiBaseConfig, tomoAppInfo: TomoAppInfo): NetworkAPIs;
311
311
  getCacheId(chainType: ChainTypeEnum | ""): string;
312
+ /** Map ChainTypeEnum to network-data platformType where they differ */
313
+ private static readonly platformTypeForChain;
312
314
  getAllNetworks(chainType: ChainTypeEnum | ""): any[];
313
315
  getCurrentNetwork(chainType: ChainTypeEnum): Promise<string>;
314
316
  setCurrentNetwork(chainType: ChainTypeEnum | "", chainId: string): Promise<void>;
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { SupportedChainTypes, ChainTypeEnum, TomoApiDomains, cache, getExplorerUrl } from '@tomo-inc/wallet-utils';
1
+ import { ChainTypeEnum, SupportedChainTypes, cache, TomoApiDomains, getExplorerUrl } from '@tomo-inc/wallet-utils';
2
2
  import axios from 'axios';
3
3
  import CryptoJS from 'crypto-js';
4
4
  import Bignumber, { BigNumber } from 'bignumber.js';
@@ -2917,9 +2917,12 @@ function generateSignature(config) {
2917
2917
  // src/api/utils/index.ts
2918
2918
  var formatJwtToken = (jwtToken) => `Bearer ${jwtToken}`;
2919
2919
  function signRequest(params, clientId, signParams) {
2920
+ if (!params.headers) {
2921
+ params.headers = {};
2922
+ }
2920
2923
  if (typeof signParams === "string") {
2921
2924
  const jwtToken = signParams;
2922
- Object.assign(params.headers ?? {}, {
2925
+ Object.assign(params.headers, {
2923
2926
  "client-id": clientId,
2924
2927
  Authorization: formatJwtToken(jwtToken)
2925
2928
  });
@@ -2934,7 +2937,7 @@ function signRequest(params, clientId, signParams) {
2934
2937
  apiSecret,
2935
2938
  salt
2936
2939
  });
2937
- Object.assign(params.headers ?? {}, {
2940
+ Object.assign(params.headers, {
2938
2941
  "X-APP-Key": apiKey,
2939
2942
  "X-Signature": signature,
2940
2943
  "X-Timestamp": timestamp,
@@ -3846,11 +3849,17 @@ var NetworkAPIs = class _NetworkAPIs extends BasePublicService {
3846
3849
  getCacheId(chainType) {
3847
3850
  return `tomo-${chainType}-currentChainId`;
3848
3851
  }
3852
+ /** Map ChainTypeEnum to network-data platformType where they differ */
3853
+ static platformTypeForChain = {
3854
+ [ChainTypeEnum.DOGECOIN]: "DOGE",
3855
+ [ChainTypeEnum.BITCOIN]: "BTC"
3856
+ };
3849
3857
  getAllNetworks(chainType) {
3850
3858
  if (chainType === "") {
3851
3859
  return this.chains;
3852
3860
  }
3853
- return this.chains.filter((chain) => chain.platformType === chainType.toUpperCase());
3861
+ const platformType = _NetworkAPIs.platformTypeForChain[chainType] ?? chainType.toUpperCase();
3862
+ return this.chains.filter((chain) => chain.platformType === platformType);
3854
3863
  }
3855
3864
  async getCurrentNetwork(chainType) {
3856
3865
  if (!SupportedChainTypes?.[chainType]) {
@@ -3960,15 +3969,16 @@ function fromBase64(base64) {
3960
3969
  return new Uint8Array(buffer);
3961
3970
  }
3962
3971
  function toBase58(data) {
3972
+ console.warn("toBase58:", data);
3963
3973
  throw new Error("toBase58 requires bs58 package. Install it: pnpm add bs58");
3964
3974
  }
3965
- var BaseConfig = SupportedChainTypes[ChainTypeEnum.DOGE];
3975
+ var BaseConfig = SupportedChainTypes[ChainTypeEnum.DOGECOIN];
3966
3976
  var BLOCK_CONFIRMATIONS = 1;
3967
3977
  var FEE_RATE_KB = 0.5;
3968
3978
  var DECIMALS = 1e8;
3969
3979
  var TRANSACTION_PAGE_SIZE = 10;
3970
3980
  var MYDOGE_BASE_URL = "https://api.mydoge.com";
3971
- var RPC_URL_TOMO = "https://wallet-pro.tomo.inc/rpc/v1/doge_coin";
3981
+ var RPC_URL_TOMO = "https://wallet-test.tomo.inc/rpc/v1/doge_coin";
3972
3982
  var RPC_URL = "https://api.bitcore.io/api/DOGE/mainnet";
3973
3983
  var RPC_TIMEOUT = 20 * 1e3;
3974
3984
  var TX_OVERHEAD = 10;
@@ -4559,11 +4569,7 @@ var DogecoinService = class _DogecoinService extends BaseService {
4559
4569
  gasLimitParam,
4560
4570
  addressList: [txData.from]
4561
4571
  };
4562
- const {
4563
- data: gasInfo,
4564
- success,
4565
- message
4566
- } = await this.transactions.queryGasInfo({
4572
+ const { data: gasInfo, success } = await this.transactions.queryGasInfo({
4567
4573
  chainType: this.chainType,
4568
4574
  params: queryGasParams
4569
4575
  });
@@ -4615,6 +4621,9 @@ var DogecoinService = class _DogecoinService extends BaseService {
4615
4621
  async signPsbt({ psbtHex, options }) {
4616
4622
  const psbtBase64 = toBase64(fromHex(psbtHex));
4617
4623
  const signedPsbt = await this.accountInfo.signTransaction(JSON.stringify({ psbtBase64 }));
4624
+ if (!options) {
4625
+ console.warn("not support options.");
4626
+ }
4618
4627
  if (!signedPsbt) {
4619
4628
  throw new Error("error psbtHex:" + psbtHex);
4620
4629
  }
@@ -4622,6 +4631,7 @@ var DogecoinService = class _DogecoinService extends BaseService {
4622
4631
  return signedRawTx;
4623
4632
  }
4624
4633
  async signPsbts({ psbtHexs, options }) {
4634
+ console.warn("signPsbsts:", psbtHexs, options);
4625
4635
  throw new Error("not implemented");
4626
4636
  }
4627
4637
  async requestTransaction(txData) {
@@ -4651,6 +4661,9 @@ var DogecoinService = class _DogecoinService extends BaseService {
4651
4661
  fee = 0,
4652
4662
  options
4653
4663
  }) {
4664
+ if (options) {
4665
+ console.warn("not support options");
4666
+ }
4654
4667
  if (fee <= 0) {
4655
4668
  throw new Error("fee is required");
4656
4669
  }
@@ -4745,7 +4758,7 @@ var TxTypes = /* @__PURE__ */ ((TxTypes2) => {
4745
4758
 
4746
4759
  // src/evm/utils.ts
4747
4760
  var isEvmChain = (network2) => {
4748
- return network2 && network2?.platformType === "EVM";
4761
+ return network2?.platformType === "EVM" || false;
4749
4762
  };
4750
4763
  var getAllTypeChainIds = ({ chainId, chainType }) => {
4751
4764
  if (isHex(chainId)) {
@@ -4759,7 +4772,7 @@ var getAllTypeChainIds = ({ chainId, chainType }) => {
4759
4772
  }
4760
4773
  const chainIdHex = toHex$1(Number(chainId));
4761
4774
  return {
4762
- chainId,
4775
+ chainId: String(chainId),
4763
4776
  chainIdHex,
4764
4777
  chainUid: `${chainType}:${chainId}`
4765
4778
  };
@@ -5073,7 +5086,7 @@ var EvmService = class _EvmService extends BaseService {
5073
5086
  }
5074
5087
  }
5075
5088
  };
5076
- var BaseConfig2 = SupportedChainTypes[ChainTypeEnum.SOL];
5089
+ var BaseConfig2 = SupportedChainTypes[ChainTypeEnum.SOLANA];
5077
5090
  var TOKEN_METADATA_PROGRAM_ID = "metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s";
5078
5091
  var MSG_PREFIX = "\xFFsolana offchain";
5079
5092
 
@@ -5112,15 +5125,7 @@ async function createLegacyTx({ from = "", to = "", amount = 0 }, connection) {
5112
5125
  transaction.lastValidBlockHeight = lastValidBlockHeight;
5113
5126
  return transaction;
5114
5127
  }
5115
- async function createTokenLegacyTransaction2({
5116
- from = "",
5117
- to = "",
5118
- amount = 0,
5119
- tokenAddress = "",
5120
- priorityFee = 0,
5121
- // microLamports (1 SOL = 1e6 microLamports)
5122
- decimals = 6
5123
- }, connection) {
5128
+ async function createTokenLegacyTransaction2({ from = "", to = "", amount = 0, tokenAddress = "", decimals = 6 }, connection) {
5124
5129
  try {
5125
5130
  const fromPubkey = new PublicKey(from);
5126
5131
  const toPubkey = new PublicKey(to);
@@ -5273,7 +5278,7 @@ var SolanaService = class _SolanaService extends BaseService {
5273
5278
  VersionedTransaction.deserialize(hexBuffer);
5274
5279
  rawTx = hexBuffer;
5275
5280
  } catch (error) {
5276
- const base58Buffer = Buffer.from(toBase58());
5281
+ const base58Buffer = Buffer.from(toBase58(signedTx));
5277
5282
  VersionedTransaction.deserialize(base58Buffer);
5278
5283
  rawTx = base58Buffer;
5279
5284
  }
@@ -5325,9 +5330,11 @@ var SolanaService = class _SolanaService extends BaseService {
5325
5330
  return signature;
5326
5331
  }
5327
5332
  async signAllTransactions({ rawTransactions }) {
5333
+ console.warn("signAllTransactions:", rawTransactions);
5328
5334
  throw new Error("no support");
5329
5335
  }
5330
5336
  async signAndSendAllTransactions({ rawTransactions }) {
5337
+ console.warn("signAndSendAllTransactions:", rawTransactions);
5331
5338
  throw new Error("no support");
5332
5339
  }
5333
5340
  async queryRent(params) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tomo-inc/chains-service",
3
- "version": "0.0.23",
3
+ "version": "0.0.24",
4
4
  "author": "tomo.inc",
5
5
  "license": "MIT",
6
6
  "private": false,
@@ -28,6 +28,7 @@
28
28
  "devDependencies": {
29
29
  "@types/supertest": "^2.0.12",
30
30
  "@vitest/browser": "^3.2.4",
31
+ "@vitest/coverage-v8": "^3.2.4",
31
32
  "playwright": "^1.44.1",
32
33
  "supertest": "^6.3.0",
33
34
  "tsup": "^8.0.0",
package/project.json CHANGED
@@ -50,7 +50,7 @@
50
50
  "executor": "nx:run-commands",
51
51
  "outputs": ["{projectRoot}/coverage"],
52
52
  "options": {
53
- "command": "vitest run",
53
+ "command": "vitest run --coverage",
54
54
  "cwd": "packages/chains-service"
55
55
  }
56
56
  },
@@ -0,0 +1,46 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { CONFIG, getConfig } from "../config";
3
+
4
+ describe("config", () => {
5
+ describe("getConfig", () => {
6
+ it("should throw when tomo stage is invalid", () => {
7
+ expect(() => getConfig("invalid" as any)).toThrow("Invalid tomo stage");
8
+ });
9
+ });
10
+
11
+ describe("CONFIG", () => {
12
+ it("should have config for prod stage", () => {
13
+ expect(CONFIG.prod).toBeDefined();
14
+ expect(CONFIG.prod.rpcBaseUrl).toBeDefined();
15
+ expect(CONFIG.prod.walletBaseUrl).toBeDefined();
16
+ expect(CONFIG.prod.txBaseUrl).toBeDefined();
17
+ expect(CONFIG.prod.tokenBaseUrl).toBeDefined();
18
+ expect(CONFIG.prod.userBaseUrl).toBeDefined();
19
+ });
20
+
21
+ it("should have config for pre stage", () => {
22
+ expect(CONFIG.pre).toBeDefined();
23
+ expect(CONFIG.pre.rpcBaseUrl).toBeDefined();
24
+ expect(CONFIG.pre.walletBaseUrl).toBeDefined();
25
+ expect(CONFIG.pre.txBaseUrl).toBeDefined();
26
+ expect(CONFIG.pre.tokenBaseUrl).toBeDefined();
27
+ expect(CONFIG.pre.userBaseUrl).toBeDefined();
28
+ });
29
+
30
+ it("should have config for dev stage", () => {
31
+ expect(CONFIG.dev).toBeDefined();
32
+ expect(CONFIG.dev.rpcBaseUrl).toBeDefined();
33
+ expect(CONFIG.dev.walletBaseUrl).toBeDefined();
34
+ expect(CONFIG.dev.txBaseUrl).toBeDefined();
35
+ expect(CONFIG.dev.tokenBaseUrl).toBeDefined();
36
+ expect(CONFIG.dev.userBaseUrl).toBeDefined();
37
+ });
38
+
39
+ it("should have correct URL structure", () => {
40
+ expect(CONFIG.dev.walletBaseUrl).toContain("/wallet");
41
+ expect(CONFIG.dev.txBaseUrl).toContain("/quote");
42
+ expect(CONFIG.dev.tokenBaseUrl).toBeDefined();
43
+ expect(CONFIG.dev.userBaseUrl).toContain("/user/api");
44
+ });
45
+ });
46
+ });
@@ -0,0 +1,147 @@
1
+ import * as walletUtils from "@tomo-inc/wallet-utils";
2
+ import { beforeEach, describe, expect, it, vi } from "vitest";
3
+ import { addUsedUtxos, getUsedUtxos, toBitcoin, toSatoshi, TransactionParser } from "../dogecoin/utils";
4
+
5
+ // Mock cache while preserving other exports
6
+ vi.mock("@tomo-inc/wallet-utils", async (importOriginal) => {
7
+ const actual = await importOriginal<typeof import("@tomo-inc/wallet-utils")>();
8
+ return {
9
+ ...actual,
10
+ cache: {
11
+ get: vi.fn(),
12
+ set: vi.fn(),
13
+ },
14
+ };
15
+ });
16
+
17
+ describe("dogecoin utils", () => {
18
+ beforeEach(() => {
19
+ vi.clearAllMocks();
20
+ });
21
+
22
+ describe("toSatoshi", () => {
23
+ it("should convert DOGE to satoshi", () => {
24
+ expect(toSatoshi(1)).toBe(100000000);
25
+ expect(toSatoshi(0.5)).toBe(50000000);
26
+ expect(toSatoshi("1")).toBe(100000000);
27
+ });
28
+
29
+ it("should throw error for invalid amount", () => {
30
+ expect(() => toSatoshi(-1)).toThrow("Invalid amount");
31
+ expect(() => toSatoshi("invalid")).toThrow();
32
+ });
33
+
34
+ it("should handle zero amount", () => {
35
+ expect(toSatoshi(0)).toBe(0);
36
+ });
37
+ });
38
+
39
+ describe("toBitcoin", () => {
40
+ it("should convert satoshi to DOGE", () => {
41
+ expect(toBitcoin(100000000)).toBe(1);
42
+ expect(toBitcoin(50000000)).toBe(0.5);
43
+ expect(toBitcoin("100000000")).toBe(1);
44
+ });
45
+
46
+ it("should throw error for invalid amount", () => {
47
+ expect(() => toBitcoin(-1)).toThrow("Invalid Koinu amount");
48
+ expect(() => toBitcoin("invalid")).toThrow();
49
+ });
50
+
51
+ it("should handle zero amount", () => {
52
+ expect(toBitcoin(0)).toBe(0);
53
+ });
54
+ });
55
+
56
+ describe("addUsedUtxos", () => {
57
+ it("should add used UTXOs to cache", () => {
58
+ const cache = vi.mocked(walletUtils.cache);
59
+ cache.get.mockReturnValue({});
60
+ cache.set.mockImplementation(() => true);
61
+
62
+ const newUsedUtxos = {
63
+ txid1: 1,
64
+ txid2: 1,
65
+ };
66
+
67
+ addUsedUtxos(newUsedUtxos);
68
+
69
+ expect(cache.set).toHaveBeenCalled();
70
+ });
71
+ });
72
+
73
+ describe("getUsedUtxos", () => {
74
+ it("should get used UTXOs from cache", () => {
75
+ const cache = vi.mocked(walletUtils.cache);
76
+ const mockUsedUtxos = { txid1: 1, txid2: 1 };
77
+ cache.get.mockReturnValue(mockUsedUtxos);
78
+
79
+ const result = getUsedUtxos();
80
+ expect(result).toEqual(mockUsedUtxos);
81
+ });
82
+
83
+ it("should return empty object if cache is empty", () => {
84
+ const cache = vi.mocked(walletUtils.cache);
85
+ cache.get.mockReturnValue(null);
86
+
87
+ const result = getUsedUtxos();
88
+ expect(result).toEqual({});
89
+ });
90
+ });
91
+
92
+ describe("TransactionParser", () => {
93
+ it("should create parser instance", () => {
94
+ const parser = new TransactionParser("rawTxHex");
95
+ expect(parser.rawTx).toBe("rawTxHex");
96
+ });
97
+
98
+ describe("hexToText", () => {
99
+ it("should convert hex to text", () => {
100
+ const parser = new TransactionParser("");
101
+ const result = parser.hexToText("48656c6c6f"); // "Hello" in hex
102
+ expect(result).toBe("Hello");
103
+ });
104
+
105
+ it("should handle empty hex", () => {
106
+ const parser = new TransactionParser("");
107
+ const result = parser.hexToText("");
108
+ expect(result).toBe("");
109
+ });
110
+ });
111
+
112
+ describe("extractOPReturnData", () => {
113
+ it("should extract OP_RETURN data when present", () => {
114
+ const rawTx = "6f72647b2274797065223a2274657374227d"; // Contains "ord" and JSON
115
+ const parser = new TransactionParser(rawTx);
116
+ const result = parser.extractOPReturnData();
117
+ expect(result).toBeDefined();
118
+ });
119
+
120
+ it("should return null when OP_RETURN data not present", () => {
121
+ const parser = new TransactionParser("normalTxData");
122
+ const result = parser.extractOPReturnData();
123
+ expect(result).toBeNull();
124
+ });
125
+ });
126
+
127
+ describe("parseInputs", () => {
128
+ it("should parse transaction inputs", () => {
129
+ const rawTx = "0100000001" + "a".repeat(64) + "00000000" + "6f7264";
130
+ const parser = new TransactionParser(rawTx);
131
+ const inputs = parser.parseInputs();
132
+ expect(Array.isArray(inputs)).toBe(true);
133
+ });
134
+ });
135
+
136
+ describe("parseScript", () => {
137
+ it("should parse transaction script", () => {
138
+ const rawTx = "0100000001" + "a".repeat(64) + "00000000";
139
+ const parser = new TransactionParser(rawTx);
140
+ const result = parser.parseScript();
141
+ expect(result).toHaveProperty("version");
142
+ expect(result).toHaveProperty("inputCount");
143
+ expect(result).toHaveProperty("inputs");
144
+ });
145
+ });
146
+ });
147
+ });