@tomo-inc/chains-service 0.0.7 → 0.0.9

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tomo-inc/chains-service",
3
- "version": "0.0.7",
3
+ "version": "0.0.9",
4
4
  "author": "tomo.inc",
5
5
  "license": "MIT",
6
6
  "private": false,
@@ -23,7 +23,7 @@
23
23
  "bitcoinjs-lib": "^7.0.0",
24
24
  "crypto-js": "4.2.0",
25
25
  "viem": "2.21.54",
26
- "@tomo-inc/wallet-utils": "0.0.6"
26
+ "@tomo-inc/wallet-utils": "0.0.8"
27
27
  },
28
28
  "devDependencies": {
29
29
  "@types/supertest": "^2.0.12",
@@ -30,12 +30,40 @@ export const loadNetworks = (WALLET_DOMAIN: string) => {
30
30
  supportHistory: false,
31
31
  },
32
32
  {
33
- chainId: 221122420,
34
- chainIndex: 22112242000,
35
- name: "DOGEOS_DEVNET",
36
- chainName: "DogeOS Devnet",
33
+ chainId: 26888,
34
+ chainIndex: 2688800,
35
+ name: "ABCORE_TESTNET",
36
+ chainName: "AB Core Testnet",
37
+ rpcUrls: ["https://rpc.core.testnet.ab.org"],
38
+ blockExplorerUrl: "https://explorer.core.testnet.ab.org",
39
+ platformType: "EVM",
40
+ isTestnet: true,
41
+ icon: "/assets/ab.svg",
42
+ supportSwap: true,
43
+ supportGift: false,
44
+ supportHistory: true,
45
+ },
46
+ {
47
+ chainId: 36888,
48
+ chainIndex: 3688800,
49
+ name: "ABCORE",
50
+ chainName: "AB Core",
51
+ rpcUrls: ["https://rpc1.core.ab.org"],
52
+ blockExplorerUrl: "https://explorer.core.ab.org",
53
+ platformType: "EVM",
54
+ isTestnet: false,
55
+ icon: "/assets/ab.svg",
56
+ supportSwap: true,
57
+ supportGift: false,
58
+ supportHistory: true,
59
+ },
60
+ {
61
+ chainId: 6281971,
62
+ chainIndex: 628197100,
63
+ name: "DOGEOS_TESTNET",
64
+ chainName: "DogeOS Testnet",
37
65
  rpcUrls: [`${WALLET_DOMAIN}/rpc/v1/doge_test`],
38
- blockExplorerUrl: "https://blockscout.devnet.doge.xyz",
66
+ blockExplorerUrl: "https://rpc.testnet.dogeos.com",
39
67
  platformType: "EVM",
40
68
  isTestnet: true,
41
69
  icon: "/assets/dogeos.svg",
package/src/api/token.ts CHANGED
@@ -43,11 +43,16 @@ export class TokenAPIs extends BasePublicService {
43
43
  }
44
44
  }
45
45
 
46
- async getTokenRisk(params: { chainIndex: number; tokenAddress: string }): Promise<RemoteResponse<any>> {
47
- if (typeof params.chainIndex !== "number" || !params.tokenAddress) {
46
+ async getTokenRisk(params: GetTokenInfoParams): Promise<RemoteResponse<any>> {
47
+ if (typeof params.chainIndex !== "number" || !params.address) {
48
48
  throw new Error("chainName or tokenAddress is required");
49
49
  }
50
- const res = await this.tokenApi.post("/v1/market/risk/details", [params]);
50
+ const res = await this.tokenApi.post("/v1/market/risk/details", [
51
+ {
52
+ chainIndex: params.chainIndex,
53
+ tokenAddress: params.address,
54
+ },
55
+ ]);
51
56
  return {
52
57
  success: res?.data?.code === "0",
53
58
  message: res?.data?.msg,
@@ -142,13 +147,13 @@ export class TokenAPIs extends BasePublicService {
142
147
  }
143
148
  }
144
149
 
145
- async getTokenDetail(params: { chainIndex: number; tokenAddress: string }): Promise<RemoteResponse<any>> {
150
+ async getTokenDetail(params: GetTokenInfoParams): Promise<RemoteResponse<any>> {
146
151
  //bad design, should: chainId + tokenAddress
147
- const { chainIndex, tokenAddress } = params;
152
+ const { chainIndex, address } = params;
148
153
 
149
154
  const res = await this.tokenApi.get(`/v1/market/token/detail`, {
150
155
  params: {
151
- tokenAddress,
156
+ tokenAddress: address,
152
157
  chainIndex,
153
158
  },
154
159
  });
@@ -4,23 +4,23 @@ import { Transactions } from "./transaction";
4
4
 
5
5
  import { CONFIG } from "../config";
6
6
  import { tomoPublicApiService } from "../api";
7
- import { TomoAppInfo } from "../types";
7
+ import { IAccountInfo, TomoAppInfo } from "../types";
8
8
 
9
9
  export class BaseService {
10
10
  public isDappConnected: boolean;
11
11
  public approveParams: any;
12
- public accountInfo: any;
12
+ public accountInfo: IAccountInfo;
13
13
  public networks: Networks;
14
14
  public tokens: Tokens;
15
15
  public transactions: Transactions;
16
16
 
17
- public constructor(tomoAppInfo: TomoAppInfo, accountInfo?: any) {
17
+ public constructor(tomoAppInfo: TomoAppInfo, accountInfo?: IAccountInfo) {
18
18
  if (!tomoAppInfo.tomoStage || !CONFIG[tomoAppInfo.tomoStage]) {
19
19
  throw new Error("Tomo stage is required");
20
20
  }
21
21
  const baseUrlConfig = CONFIG[tomoAppInfo.tomoStage];
22
22
  const { tokenAPIs, transactionAPIs, networkAPIs } = tomoPublicApiService(baseUrlConfig, tomoAppInfo);
23
- this.accountInfo = accountInfo;
23
+ this.accountInfo = (accountInfo || null) as IAccountInfo;
24
24
  this.networks = new Networks(networkAPIs);
25
25
  this.tokens = new Tokens(tokenAPIs);
26
26
  this.transactions = new Transactions(transactionAPIs);
package/src/base/token.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  //types
2
2
  import { TokenInfo } from "../types";
3
3
  import { TokenAPIs } from "../api/token";
4
+ import { GetTokenInfoParams } from "../api/types";
4
5
 
5
6
  export class Tokens {
6
7
  public tokenAPIs: TokenAPIs;
@@ -9,8 +10,8 @@ export class Tokens {
9
10
  this.tokenAPIs = tokenService;
10
11
  }
11
12
 
12
- public async searchTokens({ chainIndex, query }: { chainIndex?: number; query?: string }): Promise<TokenInfo[]> {
13
- const { data: tokens = [] }: any = await this.tokenAPIs.queryRemoteTokens({ keyword: query || "", chainIndex });
13
+ public async searchTokens({ chainIndex, keyword }: { chainIndex?: number; keyword: string }): Promise<TokenInfo[]> {
14
+ const { data: tokens = [] }: any = await this.tokenAPIs.queryRemoteTokens({ keyword, chainIndex });
14
15
  return tokens;
15
16
  }
16
17
 
@@ -19,19 +20,17 @@ export class Tokens {
19
20
  // return tokenInfoData;
20
21
  // }
21
22
 
22
- public async getTokenInfo({ address, chainIndex }: { address: string; chainIndex: number }): Promise<TokenInfo> {
23
- const {
24
- data: { data: tokenInfo },
25
- }: any = await this.tokenAPIs.getTokenInfo({ address, chainIndex });
26
- return tokenInfo;
23
+ public async getTokenInfo({ address, chainIndex }: GetTokenInfoParams): Promise<TokenInfo> {
24
+ const res: any = await this.tokenAPIs.getTokenInfo({ address, chainIndex });
25
+ return res?.data?.data;
27
26
  }
28
27
 
29
- public async getTokenRiskInfo(_params: { chainIndex: number; tokenAddress: string }): Promise<any> {
28
+ public async getTokenRiskInfo(_params: GetTokenInfoParams): Promise<any> {
30
29
  const { data: tokenRiskInfo }: any = await this.tokenAPIs.getTokenRisk(_params);
31
30
  return tokenRiskInfo;
32
31
  }
33
32
 
34
- public async getTokenDetail(_params: { chainName: string; chainIndex: number; tokenAddress: string }): Promise<any> {
33
+ public async getTokenDetail(_params: GetTokenInfoParams): Promise<any> {
35
34
  const { data }: any = await this.tokenAPIs.getTokenDetail(_params);
36
35
  return data;
37
36
  }
@@ -3,8 +3,7 @@ import axios from "axios";
3
3
  import { TRANSACTION_PAGE_SIZE, BLOCK_CONFIRMATIONS, FEE_RATE_KB } from "./config";
4
4
  import { RPC_URL, MYDOGE_BASE_URL, RPC_TIMEOUT, TX_SIZE } from "./config";
5
5
  import { TransactionParser, toSatoshi, toBitcoin } from "./utils";
6
- import { cache } from "@tomo-inc/wallet-utils";
7
- import { DogeSpendableUtxos, DunesTransactionParams } from "./type";
6
+ import { DogeSpendableUtxos } from "./type";
8
7
 
9
8
  export const mydoge = axios.create({
10
9
  baseURL: MYDOGE_BASE_URL,
@@ -29,7 +28,7 @@ export async function getBalance(address?: string) {
29
28
  return res.data || {};
30
29
  }
31
30
 
32
- export type Drc20Transaction = {
31
+ export type Transaction = {
33
32
  blockHash: string;
34
33
  blockHeight: number;
35
34
  blockTime: number;
@@ -57,13 +56,11 @@ export type Drc20Transaction = {
57
56
  hex: string;
58
57
  isAddress: boolean;
59
58
  }[];
60
- tick?: string;
61
- tickAmount?: number;
62
- drc20Detail?: Drc20Detail;
63
59
  };
64
- export async function getTxDetail(txId: string): Promise<Drc20Transaction> {
60
+
61
+ export async function getTxDetail(txId: string): Promise<Transaction> {
65
62
  if (!txId) {
66
- return {} as Drc20Transaction;
63
+ return {} as Transaction;
67
64
  }
68
65
  const path = `/tx/${txId}`;
69
66
  const api = `${MYDOGE_BASE_URL}/wallet/info?route=` + encodeURIComponent(path);
@@ -73,59 +70,6 @@ export async function getTxDetail(txId: string): Promise<Drc20Transaction> {
73
70
  return res.data || {};
74
71
  }
75
72
 
76
- export async function getAccountDrc20List(address: string, config?: any) {
77
- const api = `/drc20/${address}`;
78
- const res: any = await mydoge.get(api);
79
- return res.data || {};
80
- }
81
-
82
- const Drc20DetailsCacheKey = "Drc20Details";
83
- const Drc20DetailsCache = cache.get(Drc20DetailsCacheKey) || {};
84
- function isCacheAvailable(time: number) {
85
- const cacheTime = 20 * 60 * 1000; // 30 minutes
86
- return Date.now() - time <= cacheTime;
87
- }
88
- export type Drc20Detail = {
89
- changePercent: string;
90
- currentSupply: number;
91
- floorPrice: number;
92
- holders: number;
93
- lastPrice: number;
94
- maxSupply: number;
95
- pic: string;
96
- sales: number;
97
- tick: string;
98
- twentyFourHourVolume: string;
99
- volume: string;
100
- };
101
- export async function getDrc20Detail(ticker: string): Promise<Drc20Detail> {
102
- const drc20Detail = Drc20DetailsCache?.[ticker];
103
- if (drc20Detail?.cacheTime && isCacheAvailable(drc20Detail?.cacheTime)) {
104
- return drc20Detail;
105
- }
106
-
107
- const api = `/drc20/data/${ticker}`;
108
- const res: any = await mydoge.get(api);
109
- const detail = res.data || {};
110
- if (detail.pic) {
111
- Drc20DetailsCache[ticker] = { ...detail, cacheTime: Date.now() };
112
- cache.set(Drc20DetailsCacheKey, Drc20DetailsCache, false);
113
- }
114
- return detail;
115
- }
116
-
117
- export async function getDRC20Inscriptions(address: string, ticker: string) {
118
- const api = `${MYDOGE_BASE_URL}/inscriptions/${address}?filter=drc20&ticker=${encodeURIComponent(ticker)}`;
119
- const query = (await mydoge.get(api)).data;
120
- return query;
121
- }
122
-
123
- export async function getDRC20Balance(address: string, ticker: string) {
124
- const api = `${MYDOGE_BASE_URL}/drc20/${address}?ticker=${ticker}`;
125
- const res = (await mydoge.get(api))?.data || {};
126
- return res;
127
- }
128
-
129
73
  async function getUtxos(
130
74
  address: string,
131
75
  cursor: number,
@@ -212,100 +156,6 @@ export async function sendTransaction({ signed, senderAddress }: any) {
212
156
  return jsonrpcRes;
213
157
  }
214
158
 
215
- //nft
216
- export async function getNFTs(address?: string): Promise<{ list: any[]; total: number }> {
217
- if (!address) {
218
- throw new Error("address is required");
219
- }
220
-
221
- const res: any = await mydoge.get(`/inscriptions/${address}`);
222
- const { list = [], total = 0 } = res?.data || {};
223
- return { list, total };
224
- }
225
-
226
- export async function createNFTTransaction(params: {
227
- senderAddress: string;
228
- recipientAddress: string;
229
- location: string;
230
- inscriptionId: string;
231
- }) {
232
- const { senderAddress, recipientAddress, location, inscriptionId } = params;
233
- try {
234
- const res: any = await mydoge.post("/tx/prepare/inscription", {
235
- sender: senderAddress,
236
- recipient: recipientAddress,
237
- location: location,
238
- inscriptionId: inscriptionId,
239
- });
240
- const { rawTx, fee, amount } = res?.data || {};
241
-
242
- return {
243
- rawTx,
244
- fee,
245
- amount,
246
- };
247
- } catch (err) {
248
- console.error("createNFTTransaction", err);
249
- return {};
250
- }
251
- }
252
-
253
- //dunes
254
- export async function getDunesBalance(address: string, ticker?: string) {
255
- const api = `/dunes/${address}${ticker ? `?ticker=${ticker}` : ""}`;
256
- const res = (await mydoge.get(api))?.data || {};
257
- return res;
258
- }
259
-
260
- const DuneDetailsCacheKey = "DuneDetails";
261
- const DuneDetailsCache = cache.get(DuneDetailsCacheKey) || {};
262
- export async function getDuneDetail(ticker: string): Promise<Drc20Detail> {
263
- const duneDetail = DuneDetailsCache?.[ticker];
264
- if (duneDetail?.cacheTime && isCacheAvailable(duneDetail?.cacheTime)) {
265
- return duneDetail;
266
- }
267
- try {
268
- const api = `/dunes/data/${ticker}`;
269
- const res: any = await mydoge.get(api);
270
- const detail = res.data || {};
271
- if (detail.pic) {
272
- DuneDetailsCache[ticker] = { ...detail, cacheTime: Date.now() };
273
- cache.set(DuneDetailsCacheKey, DuneDetailsCache, false);
274
- }
275
- return detail;
276
- } catch (err) {
277
- throw new Error("dune detail not found");
278
- }
279
- }
280
-
281
- export async function createDunesTransaction(params: DunesTransactionParams) {
282
- try {
283
- const { senderAddress = "", recipientAddress = "", amount = 0, ticker = "" } = params;
284
- const { balances = [] } = await getDunesBalance(senderAddress, ticker);
285
- const { duneId } = balances[0] || {};
286
- if (!duneId) {
287
- throw new Error("duneId not found");
288
- }
289
- const response = await mydoge.post("/tx/prepare/dune", {
290
- sender: senderAddress,
291
- recipient: recipientAddress,
292
- amount,
293
- duneId,
294
- });
295
-
296
- const { rawTx, fee, inputs } = response.data;
297
-
298
- return {
299
- rawTx,
300
- fee,
301
- inputs, // usingUtxos
302
- };
303
- } catch (err) {
304
- console.error("createDunesTransaction", err);
305
- return {};
306
- }
307
- }
308
-
309
159
  export async function estimateSmartFee({ senderAddress }: { senderAddress: string }) {
310
160
  const smartfeeReq = {
311
161
  jsonrpc: "2.0",
@@ -349,8 +199,8 @@ export async function onCreateTransaction({ data, sendResponse }: { data: any; s
349
199
  }
350
200
  }
351
201
 
352
- export type Drc20TransactionResponse = {
353
- transactions: Drc20Transaction[];
202
+ export type TransactionResponse = {
203
+ transactions: Transaction[];
354
204
  txIds: string[];
355
205
  totalPages: number;
356
206
  page: number;
@@ -362,7 +212,7 @@ export async function getTransactions(
362
212
  pageSize: number;
363
213
  pageNumber: number;
364
214
  },
365
- ): Promise<Drc20TransactionResponse> {
215
+ ): Promise<TransactionResponse> {
366
216
  const { pageSize = 10, pageNumber = 1 } = config || {};
367
217
  const size = Math.min(pageSize, TRANSACTION_PAGE_SIZE);
368
218
  // Get txids
@@ -383,7 +233,7 @@ export async function getTransactions(
383
233
  totalPages = response.totalPages;
384
234
  page = response.page;
385
235
 
386
- const res = await Promise.all(
236
+ const transactions = await Promise.all(
387
237
  txIds?.map(async (txId: string) => {
388
238
  const detail = await getTxDetail(txId);
389
239
  const tx = new TransactionParser(detail.hex);
@@ -396,38 +246,7 @@ export async function getTransactions(
396
246
  }) || [],
397
247
  );
398
248
 
399
- const filterTickList = [...new Set(res.map((item) => item.tick).filter((i) => i))];
400
- const tickList = [];
401
- for (const item of filterTickList) {
402
- try {
403
- const detail = await getDrc20Detail(item);
404
- tickList.push(detail);
405
- } catch (err) {
406
- console.error(`Failed to fetch detail for ${item}`, err);
407
- tickList.push({ tick: item });
408
- }
409
- }
410
- // const tickList = await throttledMap(
411
- // filterTickList,
412
- // async (item) => {
413
- // try {
414
- // return await getDrc20Detail(item);
415
- // } catch (err) {
416
- // console.error(`Failed to fetch detail for ${item}`, err);
417
- // return { tick: item };
418
- // }
419
- // },
420
- // 1,
421
- // );
422
- const tickMap = tickList.reduce((acc, cur) => {
423
- acc[cur.tick] = cur;
424
- return acc;
425
- }, {} as any);
426
- res.forEach((item) => {
427
- item.drc20Detail = tickMap[item.tick];
428
- });
429
-
430
- return { transactions: res || [], txIds, totalPages, page };
249
+ return { transactions, txIds, totalPages, page };
431
250
  } catch (err) {
432
251
  throw new Error("getTransactions failed");
433
252
  }