@tomo-inc/chains-service 0.0.22 → 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 +50 -26
  2. package/dist/index.d.cts +5 -1
  3. package/dist/index.d.ts +5 -1
  4. package/dist/index.js +51 -27
  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 -1
  38. package/src/dogecoin/rpc.ts +33 -7
  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,14 +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";
3989
+ var RPC_URL_TOMO = "https://wallet-test.tomo.inc/rpc/v1/doge_coin";
3979
3990
  var RPC_URL = "https://api.bitcore.io/api/DOGE/mainnet";
3980
3991
  var RPC_TIMEOUT = 20 * 1e3;
3981
3992
  var TX_OVERHEAD = 10;
@@ -4183,6 +4194,10 @@ var TransactionParser = class {
4183
4194
  var mydoge = axios__default.default.create({
4184
4195
  baseURL: MYDOGE_BASE_URL
4185
4196
  });
4197
+ var tomoApi = axios__default.default.create({
4198
+ baseURL: RPC_URL_TOMO,
4199
+ timeout: RPC_TIMEOUT
4200
+ });
4186
4201
  var api = axios__default.default.create({
4187
4202
  baseURL: RPC_URL,
4188
4203
  timeout: RPC_TIMEOUT
@@ -4341,11 +4356,23 @@ var getDogeFeeByBlock = async (address, n = 22) => {
4341
4356
  };
4342
4357
  var sendDogeTx = async (rawTx) => {
4343
4358
  try {
4344
- const res = await api.post("/tx/send", { rawTx });
4345
- return res.data;
4359
+ const body = {
4360
+ jsonrpc: "2.0",
4361
+ method: "sendrawtransaction",
4362
+ params: [rawTx],
4363
+ id: 1
4364
+ };
4365
+ const res = await tomoApi.post("/", body);
4366
+ const data = res.data;
4367
+ if (data?.error) {
4368
+ return Promise.reject(new Error(data.error.message || String(data.error)));
4369
+ }
4370
+ const txid = data?.result ?? "";
4371
+ return { txid };
4346
4372
  } catch (e) {
4347
- if (typeof e?.response?.data === "string") return Promise.reject(e?.response?.data);
4348
- else return Promise.reject(e.message);
4373
+ if (typeof e?.response?.data === "string") return Promise.reject(new Error(e.response.data));
4374
+ if (e?.response?.data?.error?.message) return Promise.reject(new Error(e.response.data.error.message));
4375
+ return Promise.reject(e?.message ? new Error(e.message) : e);
4349
4376
  }
4350
4377
  };
4351
4378
 
@@ -4550,11 +4577,7 @@ var DogecoinService = class _DogecoinService extends BaseService {
4550
4577
  gasLimitParam,
4551
4578
  addressList: [txData.from]
4552
4579
  };
4553
- const {
4554
- data: gasInfo,
4555
- success,
4556
- message
4557
- } = await this.transactions.queryGasInfo({
4580
+ const { data: gasInfo, success } = await this.transactions.queryGasInfo({
4558
4581
  chainType: this.chainType,
4559
4582
  params: queryGasParams
4560
4583
  });
@@ -4606,6 +4629,9 @@ var DogecoinService = class _DogecoinService extends BaseService {
4606
4629
  async signPsbt({ psbtHex, options }) {
4607
4630
  const psbtBase64 = toBase64(fromHex(psbtHex));
4608
4631
  const signedPsbt = await this.accountInfo.signTransaction(JSON.stringify({ psbtBase64 }));
4632
+ if (!options) {
4633
+ console.warn("not support options.");
4634
+ }
4609
4635
  if (!signedPsbt) {
4610
4636
  throw new Error("error psbtHex:" + psbtHex);
4611
4637
  }
@@ -4613,6 +4639,7 @@ var DogecoinService = class _DogecoinService extends BaseService {
4613
4639
  return signedRawTx;
4614
4640
  }
4615
4641
  async signPsbts({ psbtHexs, options }) {
4642
+ console.warn("signPsbsts:", psbtHexs, options);
4616
4643
  throw new Error("not implemented");
4617
4644
  }
4618
4645
  async requestTransaction(txData) {
@@ -4642,6 +4669,9 @@ var DogecoinService = class _DogecoinService extends BaseService {
4642
4669
  fee = 0,
4643
4670
  options
4644
4671
  }) {
4672
+ if (options) {
4673
+ console.warn("not support options");
4674
+ }
4645
4675
  if (fee <= 0) {
4646
4676
  throw new Error("fee is required");
4647
4677
  }
@@ -4736,7 +4766,7 @@ var TxTypes = /* @__PURE__ */ ((TxTypes2) => {
4736
4766
 
4737
4767
  // src/evm/utils.ts
4738
4768
  var isEvmChain = (network2) => {
4739
- return network2 && network2?.platformType === "EVM";
4769
+ return network2?.platformType === "EVM" || false;
4740
4770
  };
4741
4771
  var getAllTypeChainIds = ({ chainId, chainType }) => {
4742
4772
  if (viem.isHex(chainId)) {
@@ -4750,7 +4780,7 @@ var getAllTypeChainIds = ({ chainId, chainType }) => {
4750
4780
  }
4751
4781
  const chainIdHex = viem.toHex(Number(chainId));
4752
4782
  return {
4753
- chainId,
4783
+ chainId: String(chainId),
4754
4784
  chainIdHex,
4755
4785
  chainUid: `${chainType}:${chainId}`
4756
4786
  };
@@ -5064,7 +5094,7 @@ var EvmService = class _EvmService extends BaseService {
5064
5094
  }
5065
5095
  }
5066
5096
  };
5067
- var BaseConfig2 = walletUtils.SupportedChainTypes[walletUtils.ChainTypeEnum.SOL];
5097
+ var BaseConfig2 = walletUtils.SupportedChainTypes[walletUtils.ChainTypeEnum.SOLANA];
5068
5098
  var TOKEN_METADATA_PROGRAM_ID = "metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s";
5069
5099
  var MSG_PREFIX = "\xFFsolana offchain";
5070
5100
 
@@ -5103,15 +5133,7 @@ async function createLegacyTx({ from = "", to = "", amount = 0 }, connection) {
5103
5133
  transaction.lastValidBlockHeight = lastValidBlockHeight;
5104
5134
  return transaction;
5105
5135
  }
5106
- async function createTokenLegacyTransaction2({
5107
- from = "",
5108
- to = "",
5109
- amount = 0,
5110
- tokenAddress = "",
5111
- priorityFee = 0,
5112
- // microLamports (1 SOL = 1e6 microLamports)
5113
- decimals = 6
5114
- }, connection) {
5136
+ async function createTokenLegacyTransaction2({ from = "", to = "", amount = 0, tokenAddress = "", decimals = 6 }, connection) {
5115
5137
  try {
5116
5138
  const fromPubkey = new web3_js.PublicKey(from);
5117
5139
  const toPubkey = new web3_js.PublicKey(to);
@@ -5264,7 +5286,7 @@ var SolanaService = class _SolanaService extends BaseService {
5264
5286
  web3_js.VersionedTransaction.deserialize(hexBuffer);
5265
5287
  rawTx = hexBuffer;
5266
5288
  } catch (error) {
5267
- const base58Buffer = Buffer.from(toBase58());
5289
+ const base58Buffer = Buffer.from(toBase58(signedTx));
5268
5290
  web3_js.VersionedTransaction.deserialize(base58Buffer);
5269
5291
  rawTx = base58Buffer;
5270
5292
  }
@@ -5316,9 +5338,11 @@ var SolanaService = class _SolanaService extends BaseService {
5316
5338
  return signature;
5317
5339
  }
5318
5340
  async signAllTransactions({ rawTransactions }) {
5341
+ console.warn("signAllTransactions:", rawTransactions);
5319
5342
  throw new Error("no support");
5320
5343
  }
5321
5344
  async signAndSendAllTransactions({ rawTransactions }) {
5345
+ console.warn("signAndSendAllTransactions:", rawTransactions);
5322
5346
  throw new Error("no support");
5323
5347
  }
5324
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>;
@@ -491,7 +493,9 @@ declare function getTransactions(address: string, config?: {
491
493
  pageNumber: number;
492
494
  }): Promise<TransactionResponse>;
493
495
  declare const getDogeFeeByBlock: (address?: string, n?: number) => Promise<number>;
494
- declare const sendDogeTx: (rawTx: string) => Promise<any>;
496
+ declare const sendDogeTx: (rawTx: string) => Promise<{
497
+ txid: any;
498
+ }>;
495
499
 
496
500
  type API_Transaction = Transaction;
497
501
  type API_TransactionResponse = TransactionResponse;
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>;
@@ -491,7 +493,9 @@ declare function getTransactions(address: string, config?: {
491
493
  pageNumber: number;
492
494
  }): Promise<TransactionResponse>;
493
495
  declare const getDogeFeeByBlock: (address?: string, n?: number) => Promise<number>;
494
- declare const sendDogeTx: (rawTx: string) => Promise<any>;
496
+ declare const sendDogeTx: (rawTx: string) => Promise<{
497
+ txid: any;
498
+ }>;
495
499
 
496
500
  type API_Transaction = Transaction;
497
501
  type API_TransactionResponse = TransactionResponse;
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,14 +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";
3981
+ var RPC_URL_TOMO = "https://wallet-test.tomo.inc/rpc/v1/doge_coin";
3971
3982
  var RPC_URL = "https://api.bitcore.io/api/DOGE/mainnet";
3972
3983
  var RPC_TIMEOUT = 20 * 1e3;
3973
3984
  var TX_OVERHEAD = 10;
@@ -4175,6 +4186,10 @@ var TransactionParser = class {
4175
4186
  var mydoge = axios.create({
4176
4187
  baseURL: MYDOGE_BASE_URL
4177
4188
  });
4189
+ var tomoApi = axios.create({
4190
+ baseURL: RPC_URL_TOMO,
4191
+ timeout: RPC_TIMEOUT
4192
+ });
4178
4193
  var api = axios.create({
4179
4194
  baseURL: RPC_URL,
4180
4195
  timeout: RPC_TIMEOUT
@@ -4333,11 +4348,23 @@ var getDogeFeeByBlock = async (address, n = 22) => {
4333
4348
  };
4334
4349
  var sendDogeTx = async (rawTx) => {
4335
4350
  try {
4336
- const res = await api.post("/tx/send", { rawTx });
4337
- return res.data;
4351
+ const body = {
4352
+ jsonrpc: "2.0",
4353
+ method: "sendrawtransaction",
4354
+ params: [rawTx],
4355
+ id: 1
4356
+ };
4357
+ const res = await tomoApi.post("/", body);
4358
+ const data = res.data;
4359
+ if (data?.error) {
4360
+ return Promise.reject(new Error(data.error.message || String(data.error)));
4361
+ }
4362
+ const txid = data?.result ?? "";
4363
+ return { txid };
4338
4364
  } catch (e) {
4339
- if (typeof e?.response?.data === "string") return Promise.reject(e?.response?.data);
4340
- else return Promise.reject(e.message);
4365
+ if (typeof e?.response?.data === "string") return Promise.reject(new Error(e.response.data));
4366
+ if (e?.response?.data?.error?.message) return Promise.reject(new Error(e.response.data.error.message));
4367
+ return Promise.reject(e?.message ? new Error(e.message) : e);
4341
4368
  }
4342
4369
  };
4343
4370
 
@@ -4542,11 +4569,7 @@ var DogecoinService = class _DogecoinService extends BaseService {
4542
4569
  gasLimitParam,
4543
4570
  addressList: [txData.from]
4544
4571
  };
4545
- const {
4546
- data: gasInfo,
4547
- success,
4548
- message
4549
- } = await this.transactions.queryGasInfo({
4572
+ const { data: gasInfo, success } = await this.transactions.queryGasInfo({
4550
4573
  chainType: this.chainType,
4551
4574
  params: queryGasParams
4552
4575
  });
@@ -4598,6 +4621,9 @@ var DogecoinService = class _DogecoinService extends BaseService {
4598
4621
  async signPsbt({ psbtHex, options }) {
4599
4622
  const psbtBase64 = toBase64(fromHex(psbtHex));
4600
4623
  const signedPsbt = await this.accountInfo.signTransaction(JSON.stringify({ psbtBase64 }));
4624
+ if (!options) {
4625
+ console.warn("not support options.");
4626
+ }
4601
4627
  if (!signedPsbt) {
4602
4628
  throw new Error("error psbtHex:" + psbtHex);
4603
4629
  }
@@ -4605,6 +4631,7 @@ var DogecoinService = class _DogecoinService extends BaseService {
4605
4631
  return signedRawTx;
4606
4632
  }
4607
4633
  async signPsbts({ psbtHexs, options }) {
4634
+ console.warn("signPsbsts:", psbtHexs, options);
4608
4635
  throw new Error("not implemented");
4609
4636
  }
4610
4637
  async requestTransaction(txData) {
@@ -4634,6 +4661,9 @@ var DogecoinService = class _DogecoinService extends BaseService {
4634
4661
  fee = 0,
4635
4662
  options
4636
4663
  }) {
4664
+ if (options) {
4665
+ console.warn("not support options");
4666
+ }
4637
4667
  if (fee <= 0) {
4638
4668
  throw new Error("fee is required");
4639
4669
  }
@@ -4728,7 +4758,7 @@ var TxTypes = /* @__PURE__ */ ((TxTypes2) => {
4728
4758
 
4729
4759
  // src/evm/utils.ts
4730
4760
  var isEvmChain = (network2) => {
4731
- return network2 && network2?.platformType === "EVM";
4761
+ return network2?.platformType === "EVM" || false;
4732
4762
  };
4733
4763
  var getAllTypeChainIds = ({ chainId, chainType }) => {
4734
4764
  if (isHex(chainId)) {
@@ -4742,7 +4772,7 @@ var getAllTypeChainIds = ({ chainId, chainType }) => {
4742
4772
  }
4743
4773
  const chainIdHex = toHex$1(Number(chainId));
4744
4774
  return {
4745
- chainId,
4775
+ chainId: String(chainId),
4746
4776
  chainIdHex,
4747
4777
  chainUid: `${chainType}:${chainId}`
4748
4778
  };
@@ -5056,7 +5086,7 @@ var EvmService = class _EvmService extends BaseService {
5056
5086
  }
5057
5087
  }
5058
5088
  };
5059
- var BaseConfig2 = SupportedChainTypes[ChainTypeEnum.SOL];
5089
+ var BaseConfig2 = SupportedChainTypes[ChainTypeEnum.SOLANA];
5060
5090
  var TOKEN_METADATA_PROGRAM_ID = "metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s";
5061
5091
  var MSG_PREFIX = "\xFFsolana offchain";
5062
5092
 
@@ -5095,15 +5125,7 @@ async function createLegacyTx({ from = "", to = "", amount = 0 }, connection) {
5095
5125
  transaction.lastValidBlockHeight = lastValidBlockHeight;
5096
5126
  return transaction;
5097
5127
  }
5098
- async function createTokenLegacyTransaction2({
5099
- from = "",
5100
- to = "",
5101
- amount = 0,
5102
- tokenAddress = "",
5103
- priorityFee = 0,
5104
- // microLamports (1 SOL = 1e6 microLamports)
5105
- decimals = 6
5106
- }, connection) {
5128
+ async function createTokenLegacyTransaction2({ from = "", to = "", amount = 0, tokenAddress = "", decimals = 6 }, connection) {
5107
5129
  try {
5108
5130
  const fromPubkey = new PublicKey(from);
5109
5131
  const toPubkey = new PublicKey(to);
@@ -5256,7 +5278,7 @@ var SolanaService = class _SolanaService extends BaseService {
5256
5278
  VersionedTransaction.deserialize(hexBuffer);
5257
5279
  rawTx = hexBuffer;
5258
5280
  } catch (error) {
5259
- const base58Buffer = Buffer.from(toBase58());
5281
+ const base58Buffer = Buffer.from(toBase58(signedTx));
5260
5282
  VersionedTransaction.deserialize(base58Buffer);
5261
5283
  rawTx = base58Buffer;
5262
5284
  }
@@ -5308,9 +5330,11 @@ var SolanaService = class _SolanaService extends BaseService {
5308
5330
  return signature;
5309
5331
  }
5310
5332
  async signAllTransactions({ rawTransactions }) {
5333
+ console.warn("signAllTransactions:", rawTransactions);
5311
5334
  throw new Error("no support");
5312
5335
  }
5313
5336
  async signAndSendAllTransactions({ rawTransactions }) {
5337
+ console.warn("signAndSendAllTransactions:", rawTransactions);
5314
5338
  throw new Error("no support");
5315
5339
  }
5316
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.22",
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
+ });