@tomo-inc/chains-service 0.0.6 → 0.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +4 -0
- package/dist/index.cjs +602 -95
- package/dist/index.d.cts +117 -43
- package/dist/index.d.ts +117 -43
- package/dist/index.js +608 -102
- package/package.json +2 -2
- package/src/api/network-data.ts +19 -5
- package/src/api/token.ts +11 -6
- package/src/base/service.ts +4 -4
- package/src/base/token.ts +8 -9
- package/src/dogecoin/service.ts +46 -252
- package/src/dogecoin/type.ts +12 -0
- package/src/dogecoin/utils-doge.ts +75 -2
- package/src/dogecoin/utils.ts +3 -380
- package/src/evm/service.ts +57 -73
- package/src/index.ts +5 -4
- package/src/solana/service.ts +6 -6
- package/src/types/account.ts +4 -3
- package/src/types/index.ts +3 -3
- package/src/utils/index.ts +7 -0
package/dist/index.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import { ChainTypes, SupportedChainTypes,
|
|
1
|
+
import { ChainTypes, SupportedChainTypes, cache, TomoApiDomains, getExplorerUrl } from '@tomo-inc/wallet-utils';
|
|
2
2
|
import Bignumber, { BigNumber } from 'bignumber.js';
|
|
3
|
-
import { toHex, parseUnits, createPublicClient, http, isHex, fromHex, parseTransaction, formatUnits, encodeFunctionData, erc20Abi } from 'viem';
|
|
3
|
+
import { toHex, parseUnits, isAddressEqual, createPublicClient, http, hexToBigInt, numberToHex, isHex, fromHex, parseTransaction, formatUnits, encodeFunctionData, erc20Abi } from 'viem';
|
|
4
4
|
import axios from 'axios';
|
|
5
5
|
import CryptoJS from 'crypto-js';
|
|
6
6
|
import { getAssociatedTokenAddress, createAssociatedTokenAccountInstruction, createTransferInstruction, TOKEN_PROGRAM_ID } from '@solana/spl-token';
|
|
7
|
-
import { PublicKey, Connection, VersionedTransaction, sendAndConfirmRawTransaction, Transaction, SystemProgram, LAMPORTS_PER_SOL } from '@solana/web3.js';
|
|
7
|
+
import { PublicKey, Connection, VersionedTransaction, sendAndConfirmRawTransaction, Transaction as Transaction$1, SystemProgram, LAMPORTS_PER_SOL } from '@solana/web3.js';
|
|
8
|
+
import { Psbt, Transaction, address } from 'bitcoinjs-lib';
|
|
8
9
|
|
|
9
10
|
var __create = Object.create;
|
|
10
11
|
var __defProp = Object.defineProperty;
|
|
@@ -2796,18 +2797,18 @@ var Networks = class {
|
|
|
2796
2797
|
return networks;
|
|
2797
2798
|
}
|
|
2798
2799
|
async getNetworkByChainId(chainId) {
|
|
2799
|
-
const
|
|
2800
|
-
if (!
|
|
2800
|
+
const network2 = await this.networkAPIs.getNetworkByChainId(chainId);
|
|
2801
|
+
if (!network2) {
|
|
2801
2802
|
throw new Error("Network not found");
|
|
2802
2803
|
}
|
|
2803
|
-
return
|
|
2804
|
+
return network2;
|
|
2804
2805
|
}
|
|
2805
2806
|
async getNetworkByChainIndex(chainIndex) {
|
|
2806
|
-
const
|
|
2807
|
-
if (!
|
|
2807
|
+
const network2 = await this.networkAPIs.getNetworkByChainIndex(chainIndex);
|
|
2808
|
+
if (!network2) {
|
|
2808
2809
|
throw new Error("Network not found");
|
|
2809
2810
|
}
|
|
2810
|
-
return
|
|
2811
|
+
return network2;
|
|
2811
2812
|
}
|
|
2812
2813
|
async getCurrentNetwork() {
|
|
2813
2814
|
const chainType = this.chainType;
|
|
@@ -2830,8 +2831,8 @@ var Tokens = class {
|
|
|
2830
2831
|
constructor(tokenService) {
|
|
2831
2832
|
this.tokenAPIs = tokenService;
|
|
2832
2833
|
}
|
|
2833
|
-
async searchTokens({ chainIndex,
|
|
2834
|
-
const { data: tokens = [] } = await this.tokenAPIs.queryRemoteTokens({ keyword
|
|
2834
|
+
async searchTokens({ chainIndex, keyword }) {
|
|
2835
|
+
const { data: tokens = [] } = await this.tokenAPIs.queryRemoteTokens({ keyword, chainIndex });
|
|
2835
2836
|
return tokens;
|
|
2836
2837
|
}
|
|
2837
2838
|
// public async addToken(tokenInfo: Omit<TokenInfo, "id">): Promise<TokenInfo> {
|
|
@@ -2839,10 +2840,8 @@ var Tokens = class {
|
|
|
2839
2840
|
// return tokenInfoData;
|
|
2840
2841
|
// }
|
|
2841
2842
|
async getTokenInfo({ address, chainIndex }) {
|
|
2842
|
-
const {
|
|
2843
|
-
|
|
2844
|
-
} = await this.tokenAPIs.getTokenInfo({ address, chainIndex });
|
|
2845
|
-
return tokenInfo;
|
|
2843
|
+
const res = await this.tokenAPIs.getTokenInfo({ address, chainIndex });
|
|
2844
|
+
return res?.data?.data;
|
|
2846
2845
|
}
|
|
2847
2846
|
async getTokenRiskInfo(_params) {
|
|
2848
2847
|
const { data: tokenRiskInfo } = await this.tokenAPIs.getTokenRisk(_params);
|
|
@@ -2972,7 +2971,7 @@ var BasePublicService = class {
|
|
|
2972
2971
|
this.apiBase = publicApiBase;
|
|
2973
2972
|
this.tomoAppInfo = tomoAppInfo;
|
|
2974
2973
|
[this.tokenApi, this.txApi, this.walletApi].map(
|
|
2975
|
-
(
|
|
2974
|
+
(api2, i) => api2.interceptors.request.use((params) => {
|
|
2976
2975
|
const { tokenBaseUrl, txBaseUrl, walletBaseUrl } = publicApiBase;
|
|
2977
2976
|
params.baseURL = [tokenBaseUrl, txBaseUrl, walletBaseUrl][i];
|
|
2978
2977
|
return signRequest(params, tomoAppInfo.tomoClientId, tomoAppInfo);
|
|
@@ -3013,10 +3012,15 @@ var TokenAPIs = class _TokenAPIs extends BasePublicService {
|
|
|
3013
3012
|
}
|
|
3014
3013
|
}
|
|
3015
3014
|
async getTokenRisk(params) {
|
|
3016
|
-
if (typeof params.chainIndex !== "number" || !params.
|
|
3015
|
+
if (typeof params.chainIndex !== "number" || !params.address) {
|
|
3017
3016
|
throw new Error("chainName or tokenAddress is required");
|
|
3018
3017
|
}
|
|
3019
|
-
const res = await this.tokenApi.post("/v1/market/risk/details", [
|
|
3018
|
+
const res = await this.tokenApi.post("/v1/market/risk/details", [
|
|
3019
|
+
{
|
|
3020
|
+
chainIndex: params.chainIndex,
|
|
3021
|
+
tokenAddress: params.address
|
|
3022
|
+
}
|
|
3023
|
+
]);
|
|
3020
3024
|
return {
|
|
3021
3025
|
success: res?.data?.code === "0",
|
|
3022
3026
|
message: res?.data?.msg,
|
|
@@ -3104,10 +3108,10 @@ var TokenAPIs = class _TokenAPIs extends BasePublicService {
|
|
|
3104
3108
|
}
|
|
3105
3109
|
}
|
|
3106
3110
|
async getTokenDetail(params) {
|
|
3107
|
-
const { chainIndex,
|
|
3111
|
+
const { chainIndex, address } = params;
|
|
3108
3112
|
const res = await this.tokenApi.get(`/v1/market/token/detail`, {
|
|
3109
3113
|
params: {
|
|
3110
|
-
tokenAddress,
|
|
3114
|
+
tokenAddress: address,
|
|
3111
3115
|
chainIndex
|
|
3112
3116
|
}
|
|
3113
3117
|
});
|
|
@@ -3259,12 +3263,26 @@ var loadNetworks = (WALLET_DOMAIN) => {
|
|
|
3259
3263
|
supportHistory: false
|
|
3260
3264
|
},
|
|
3261
3265
|
{
|
|
3262
|
-
chainId:
|
|
3263
|
-
chainIndex:
|
|
3264
|
-
name: "
|
|
3265
|
-
chainName: "
|
|
3266
|
+
chainId: 26888,
|
|
3267
|
+
chainIndex: 2688800,
|
|
3268
|
+
name: "ABCORE_TESTNET",
|
|
3269
|
+
chainName: "AB Core Testnet",
|
|
3270
|
+
rpcUrls: ["https://rpc.core.testnet.ab.org"],
|
|
3271
|
+
blockExplorerUrl: "https://explorer.core.testnet.ab.org",
|
|
3272
|
+
platformType: "EVM",
|
|
3273
|
+
isTestnet: true,
|
|
3274
|
+
icon: "/assets/ab.svg",
|
|
3275
|
+
supportSwap: true,
|
|
3276
|
+
supportGift: false,
|
|
3277
|
+
supportHistory: true
|
|
3278
|
+
},
|
|
3279
|
+
{
|
|
3280
|
+
chainId: 6281971,
|
|
3281
|
+
chainIndex: 628197100,
|
|
3282
|
+
name: "DOGEOS_TESTNET",
|
|
3283
|
+
chainName: "DogeOS Testnet",
|
|
3266
3284
|
rpcUrls: [`${WALLET_DOMAIN}/rpc/v1/doge_test`],
|
|
3267
|
-
blockExplorerUrl: "https://
|
|
3285
|
+
blockExplorerUrl: "https://rpc.testnet.dogeos.com",
|
|
3268
3286
|
platformType: "EVM",
|
|
3269
3287
|
isTestnet: true,
|
|
3270
3288
|
icon: "/assets/dogeos.svg",
|
|
@@ -3886,7 +3904,7 @@ var BaseService = class {
|
|
|
3886
3904
|
}
|
|
3887
3905
|
const baseUrlConfig = CONFIG[tomoAppInfo.tomoStage];
|
|
3888
3906
|
const { tokenAPIs, transactionAPIs, networkAPIs } = tomoPublicApiService(baseUrlConfig, tomoAppInfo);
|
|
3889
|
-
this.accountInfo = accountInfo;
|
|
3907
|
+
this.accountInfo = accountInfo || null;
|
|
3890
3908
|
this.networks = new Networks(networkAPIs);
|
|
3891
3909
|
this.tokens = new Tokens(tokenAPIs);
|
|
3892
3910
|
this.transactions = new Transactions(transactionAPIs);
|
|
@@ -3896,8 +3914,8 @@ var BaseService = class {
|
|
|
3896
3914
|
this.approveParams = params;
|
|
3897
3915
|
}
|
|
3898
3916
|
};
|
|
3899
|
-
function getRPCClient(
|
|
3900
|
-
const { chainId, name, rpcUrls, nativeCurrencyDecimals, nativeCurrencyName, nativeCurrencySymbol } =
|
|
3917
|
+
function getRPCClient(network2) {
|
|
3918
|
+
const { chainId, name, rpcUrls, nativeCurrencyDecimals, nativeCurrencyName, nativeCurrencySymbol } = network2;
|
|
3901
3919
|
const myCustomChain = {
|
|
3902
3920
|
id: Number(chainId) || chainId,
|
|
3903
3921
|
name,
|
|
@@ -3952,8 +3970,8 @@ var TxTypes = /* @__PURE__ */ ((TxTypes2) => {
|
|
|
3952
3970
|
})(TxTypes || {});
|
|
3953
3971
|
|
|
3954
3972
|
// src/evm/utils.ts
|
|
3955
|
-
var isEvmChain = (
|
|
3956
|
-
return
|
|
3973
|
+
var isEvmChain = (network2) => {
|
|
3974
|
+
return network2 && network2?.platformType === "EVM";
|
|
3957
3975
|
};
|
|
3958
3976
|
var getAllTypeChainIds = ({ chainId, chainType }) => {
|
|
3959
3977
|
if (isHex(chainId)) {
|
|
@@ -4045,7 +4063,7 @@ var EvmService = class _EvmService extends BaseService {
|
|
|
4045
4063
|
}
|
|
4046
4064
|
async personal_sign([message, address]) {
|
|
4047
4065
|
const accounts = await this.accountInfo.getCurrent();
|
|
4048
|
-
if (accounts[0].address
|
|
4066
|
+
if (!isAddressEqual(accounts[0].address, address)) {
|
|
4049
4067
|
throw new Error("address is not the current account");
|
|
4050
4068
|
}
|
|
4051
4069
|
const signature = await this.accountInfo.signMessage(message);
|
|
@@ -4053,7 +4071,7 @@ var EvmService = class _EvmService extends BaseService {
|
|
|
4053
4071
|
}
|
|
4054
4072
|
async eth_signTypedData_v4([address, typedData]) {
|
|
4055
4073
|
const accounts = await this.accountInfo.getCurrent();
|
|
4056
|
-
if (accounts[0].address
|
|
4074
|
+
if (!isAddressEqual(accounts[0].address, address)) {
|
|
4057
4075
|
throw new Error("address is not the current account");
|
|
4058
4076
|
}
|
|
4059
4077
|
const signature = await this.accountInfo.signTypedData(typedData);
|
|
@@ -4061,7 +4079,7 @@ var EvmService = class _EvmService extends BaseService {
|
|
|
4061
4079
|
}
|
|
4062
4080
|
async eth_getBalance([address, type]) {
|
|
4063
4081
|
const accounts = await this.accountInfo.getCurrent();
|
|
4064
|
-
if (accounts[0].address
|
|
4082
|
+
if (!isAddressEqual(accounts[0].address, address)) {
|
|
4065
4083
|
throw new Error("address is not the current account");
|
|
4066
4084
|
}
|
|
4067
4085
|
if (type !== "latest") {
|
|
@@ -4105,8 +4123,8 @@ var EvmService = class _EvmService extends BaseService {
|
|
|
4105
4123
|
});
|
|
4106
4124
|
if (!success) {
|
|
4107
4125
|
console.error("queryGasInfo evm", txData, queryGasParams, message, gasInfo);
|
|
4108
|
-
const
|
|
4109
|
-
const { gasFee } =
|
|
4126
|
+
const BaseConfig3 = SupportedChainTypes[ChainTypes.EVM];
|
|
4127
|
+
const { gasFee } = BaseConfig3;
|
|
4110
4128
|
return {
|
|
4111
4129
|
success: true,
|
|
4112
4130
|
gasFee: gasFee.toString()
|
|
@@ -4138,51 +4156,6 @@ var EvmService = class _EvmService extends BaseService {
|
|
|
4138
4156
|
}
|
|
4139
4157
|
};
|
|
4140
4158
|
}
|
|
4141
|
-
async eth_estimateGas(txs) {
|
|
4142
|
-
const { from, to, value = "0x1" } = txs[0] || {};
|
|
4143
|
-
const accounts = await this.accountInfo.getCurrent();
|
|
4144
|
-
if (accounts[0].address !== from) {
|
|
4145
|
-
throw new Error("address is not the current account");
|
|
4146
|
-
}
|
|
4147
|
-
if (!to) {
|
|
4148
|
-
throw new Error("to is not set");
|
|
4149
|
-
}
|
|
4150
|
-
const chainId = txs[0]?.chainId || await this.eth_chainId();
|
|
4151
|
-
const queryGasParams = {
|
|
4152
|
-
chainIndex: Number(chainId),
|
|
4153
|
-
callData: "0x",
|
|
4154
|
-
gasLimitParam: {
|
|
4155
|
-
from,
|
|
4156
|
-
to,
|
|
4157
|
-
value
|
|
4158
|
-
},
|
|
4159
|
-
addressList: [from]
|
|
4160
|
-
};
|
|
4161
|
-
const chainType = this.chainType;
|
|
4162
|
-
const {
|
|
4163
|
-
data: gasInfo,
|
|
4164
|
-
success,
|
|
4165
|
-
message
|
|
4166
|
-
} = await this.transactions.queryGasInfo({
|
|
4167
|
-
chainType,
|
|
4168
|
-
params: queryGasParams
|
|
4169
|
-
});
|
|
4170
|
-
if (!success) {
|
|
4171
|
-
console.error("queryGasInfo evm", txs, message, gasInfo);
|
|
4172
|
-
const { gasFee } = SupportedChainTypes[chainType];
|
|
4173
|
-
return gasFee.toString();
|
|
4174
|
-
}
|
|
4175
|
-
const res = getAllTypeChainIds({ chainId, chainType });
|
|
4176
|
-
const { nativeCurrencyDecimals } = await this.networks.getNetworkByChainId(res.chainId);
|
|
4177
|
-
const { baseFee = 1, gasLimit = 0 } = gasInfo;
|
|
4178
|
-
const baseFeeBN = new BigNumber(baseFee);
|
|
4179
|
-
const calcFee = (feeLevel) => {
|
|
4180
|
-
const fee = baseFeeBN.plus(gasInfo[feeLevel] || 0);
|
|
4181
|
-
const gasFee = fee.times(gasLimit);
|
|
4182
|
-
return toHex(BigInt(gasFee.toNumber()), nativeCurrencyDecimals);
|
|
4183
|
-
};
|
|
4184
|
-
return calcFee("priorityFeeMedium");
|
|
4185
|
-
}
|
|
4186
4159
|
async createPublicClient({ chainId, rpcUrl }) {
|
|
4187
4160
|
if (rpcUrl) {
|
|
4188
4161
|
return createPublicClient({
|
|
@@ -4204,6 +4177,26 @@ var EvmService = class _EvmService extends BaseService {
|
|
|
4204
4177
|
transport: http(rpcUrl)
|
|
4205
4178
|
});
|
|
4206
4179
|
}
|
|
4180
|
+
async eth_estimateGas(txs) {
|
|
4181
|
+
const { from, to, value = "0x1", chainId } = txs[0] || {};
|
|
4182
|
+
const accounts = await this.accountInfo.getCurrent();
|
|
4183
|
+
if (accounts[0].address !== from) {
|
|
4184
|
+
throw new Error("address is not the current account");
|
|
4185
|
+
}
|
|
4186
|
+
if (!to) {
|
|
4187
|
+
throw new Error("to is not set");
|
|
4188
|
+
}
|
|
4189
|
+
try {
|
|
4190
|
+
const rpcClient = await this.createPublicClient({ chainId: chainId?.toString() });
|
|
4191
|
+
const gas = await rpcClient.estimateGas({ account: from, to, value: hexToBigInt(value) });
|
|
4192
|
+
return gas;
|
|
4193
|
+
} catch (error) {
|
|
4194
|
+
console.warn("Failed to estimate gas:", error);
|
|
4195
|
+
const BaseConfig3 = SupportedChainTypes[ChainTypes.EVM];
|
|
4196
|
+
const { gasFee } = BaseConfig3;
|
|
4197
|
+
return numberToHex(parseUnits(gasFee.toString(), 18));
|
|
4198
|
+
}
|
|
4199
|
+
}
|
|
4207
4200
|
// Get nonce for current account
|
|
4208
4201
|
async eth_getTransactionCount([address, type]) {
|
|
4209
4202
|
const accounts = await this.accountInfo.getCurrent();
|
|
@@ -4232,30 +4225,35 @@ var EvmService = class _EvmService extends BaseService {
|
|
|
4232
4225
|
nonce: "number",
|
|
4233
4226
|
maxPriorityFeePerGas: "bigint",
|
|
4234
4227
|
maxFeePerGas: "bigint",
|
|
4235
|
-
|
|
4228
|
+
gasPrice: "bigint",
|
|
4236
4229
|
gas: "bigint"
|
|
4237
4230
|
};
|
|
4238
|
-
|
|
4239
|
-
|
|
4240
|
-
txData = { ...txData, gas, gasLimit: gas };
|
|
4231
|
+
const txData = txParams?.[0];
|
|
4232
|
+
txData.gas = txData?.gas || txData?.gasLimit;
|
|
4241
4233
|
txData.data = txData.data || "0x";
|
|
4234
|
+
txData.value = txData.value || "0x";
|
|
4235
|
+
txData.nonce = txData.nonce || "0x0";
|
|
4236
|
+
if (!txData?.gas || !txData?.to || !txData?.chainId) {
|
|
4237
|
+
throw new Error("gas or to or chainId is not set");
|
|
4238
|
+
}
|
|
4242
4239
|
const accounts = await this.accountInfo.getCurrent();
|
|
4243
4240
|
const address = accounts[0].address;
|
|
4244
|
-
if (txData?.from && txData?.from
|
|
4241
|
+
if (txData?.from && !isAddressEqual(txData?.from, address)) {
|
|
4245
4242
|
console.error("eth_signTransaction error data: from is not the current account", txData);
|
|
4246
4243
|
throw new Error(`eth_signTransaction error data: from is not the current account`);
|
|
4247
4244
|
}
|
|
4248
4245
|
delete txData?.from;
|
|
4246
|
+
delete txData?.gasLimit;
|
|
4249
4247
|
const preparedTx = {
|
|
4250
|
-
|
|
4251
|
-
gas: txData?.gasLimit,
|
|
4252
|
-
account: address
|
|
4248
|
+
gas: txData?.gas
|
|
4253
4249
|
};
|
|
4254
4250
|
for (const key in preparedTxPropsType) {
|
|
4255
|
-
if (
|
|
4256
|
-
|
|
4251
|
+
if (txData?.[key] && isHex(txData?.[key])) {
|
|
4252
|
+
preparedTx[key] = preparedTxPropsType[key] === "number" ? fromHex(txData[key], "number") : txData[key];
|
|
4257
4253
|
}
|
|
4258
|
-
|
|
4254
|
+
}
|
|
4255
|
+
if (txData?.type !== "legacy") {
|
|
4256
|
+
delete preparedTx.gasPrice;
|
|
4259
4257
|
}
|
|
4260
4258
|
try {
|
|
4261
4259
|
const serializedTransaction = await this.accountInfo.signTransaction(
|
|
@@ -4312,7 +4310,7 @@ var txToHex = (tx) => {
|
|
|
4312
4310
|
if (tx instanceof VersionedTransaction) {
|
|
4313
4311
|
return Buffer.from(tx.serialize()).toString("hex");
|
|
4314
4312
|
}
|
|
4315
|
-
if (tx instanceof Transaction) {
|
|
4313
|
+
if (tx instanceof Transaction$1) {
|
|
4316
4314
|
return Buffer.from(
|
|
4317
4315
|
tx.serialize({
|
|
4318
4316
|
requireAllSignatures: false,
|
|
@@ -4326,7 +4324,7 @@ async function createLegacyTx({ from = "", to = "", amount = 0 }, connection) {
|
|
|
4326
4324
|
const fromPubkey = new PublicKey(from);
|
|
4327
4325
|
const toPubkey = new PublicKey(to);
|
|
4328
4326
|
const { blockhash, lastValidBlockHeight } = await connection.getLatestBlockhash();
|
|
4329
|
-
const transaction = new Transaction().add(
|
|
4327
|
+
const transaction = new Transaction$1().add(
|
|
4330
4328
|
SystemProgram.transfer({
|
|
4331
4329
|
fromPubkey,
|
|
4332
4330
|
//payer
|
|
@@ -4356,7 +4354,7 @@ async function createTokenLegacyTransaction2({
|
|
|
4356
4354
|
const fromTokenPubKey = await getAssociatedTokenAddress(tokenPublicKey, fromPubkey);
|
|
4357
4355
|
const toTokenPubKey = await getAssociatedTokenAddress(tokenPublicKey, toPubkey);
|
|
4358
4356
|
const { blockhash } = await connection.getLatestBlockhash("confirmed");
|
|
4359
|
-
const transaction = new Transaction();
|
|
4357
|
+
const transaction = new Transaction$1();
|
|
4360
4358
|
transaction.feePayer = fromPubkey;
|
|
4361
4359
|
transaction.recentBlockhash = blockhash;
|
|
4362
4360
|
try {
|
|
@@ -4378,6 +4376,34 @@ async function createTokenLegacyTransaction2({
|
|
|
4378
4376
|
}
|
|
4379
4377
|
|
|
4380
4378
|
// src/dogecoin/base.ts
|
|
4379
|
+
function fromHex3(hex) {
|
|
4380
|
+
const cleanHex = hex.startsWith("0x") ? hex.slice(2) : hex;
|
|
4381
|
+
const paddedHex = cleanHex.length % 2 === 0 ? cleanHex : "0" + cleanHex;
|
|
4382
|
+
const bytes = new Uint8Array(paddedHex.length / 2);
|
|
4383
|
+
for (let i = 0; i < paddedHex.length; i += 2) {
|
|
4384
|
+
bytes[i / 2] = parseInt(paddedHex.substr(i, 2), 16);
|
|
4385
|
+
}
|
|
4386
|
+
return bytes;
|
|
4387
|
+
}
|
|
4388
|
+
function toHex3(data) {
|
|
4389
|
+
if (typeof data === "string") {
|
|
4390
|
+
return data.startsWith("0x") ? data.slice(2) : data;
|
|
4391
|
+
}
|
|
4392
|
+
const buffer = Buffer.isBuffer(data) ? data : Buffer.from(data);
|
|
4393
|
+
return buffer.toString("hex");
|
|
4394
|
+
}
|
|
4395
|
+
function toBase64(data) {
|
|
4396
|
+
if (typeof data === "string") {
|
|
4397
|
+
const buffer2 = Buffer.from(data, "hex");
|
|
4398
|
+
return buffer2.toString("base64");
|
|
4399
|
+
}
|
|
4400
|
+
const buffer = Buffer.isBuffer(data) ? data : Buffer.from(data);
|
|
4401
|
+
return buffer.toString("base64");
|
|
4402
|
+
}
|
|
4403
|
+
function fromBase64(base64) {
|
|
4404
|
+
const buffer = Buffer.from(base64, "base64");
|
|
4405
|
+
return new Uint8Array(buffer);
|
|
4406
|
+
}
|
|
4381
4407
|
function toBase58(data) {
|
|
4382
4408
|
throw new Error("toBase58 requires bs58 package. Install it: pnpm add bs58");
|
|
4383
4409
|
}
|
|
@@ -4414,11 +4440,11 @@ var SolanaService = class _SolanaService extends BaseService {
|
|
|
4414
4440
|
return await this.accountInfo.getCurrent();
|
|
4415
4441
|
}
|
|
4416
4442
|
async getAccount() {
|
|
4417
|
-
const { currentAddress, publicKey } = await this.accountInfo.
|
|
4443
|
+
const { address: currentAddress, publicKey } = await this.accountInfo.getCurrent();
|
|
4418
4444
|
return { publicKey: publicKey || currentAddress, address: currentAddress };
|
|
4419
4445
|
}
|
|
4420
4446
|
async signMessage(params) {
|
|
4421
|
-
const { currentAddress, publicKey } = await this.accountInfo.
|
|
4447
|
+
const { address: currentAddress, publicKey } = await this.accountInfo.getCurrent();
|
|
4422
4448
|
const { message } = params;
|
|
4423
4449
|
const signature = await this.accountInfo.signMessage(message);
|
|
4424
4450
|
return {
|
|
@@ -4428,7 +4454,7 @@ var SolanaService = class _SolanaService extends BaseService {
|
|
|
4428
4454
|
};
|
|
4429
4455
|
}
|
|
4430
4456
|
async signIn(params) {
|
|
4431
|
-
const { currentAddress, publicKey } = await this.accountInfo.
|
|
4457
|
+
const { address: currentAddress, publicKey } = await this.accountInfo.getCurrent();
|
|
4432
4458
|
const { signature = "" } = await this.signMessage(params);
|
|
4433
4459
|
return {
|
|
4434
4460
|
address: currentAddress,
|
|
@@ -4619,6 +4645,486 @@ var SolanaService = class _SolanaService extends BaseService {
|
|
|
4619
4645
|
}
|
|
4620
4646
|
}
|
|
4621
4647
|
};
|
|
4648
|
+
var BaseConfig2 = SupportedChainTypes[ChainTypes.DOGE];
|
|
4649
|
+
var DECIMALS = 1e8;
|
|
4650
|
+
var MYDOGE_BASE_URL = "https://api.mydoge.com";
|
|
4651
|
+
var RPC_URL = "https://api.bitcore.io/api/DOGE/mainnet";
|
|
4652
|
+
var RPC_TIMEOUT = 20 * 1e3;
|
|
4653
|
+
var network = {
|
|
4654
|
+
messagePrefix: "Dogecoin Signed Message:\n",
|
|
4655
|
+
bech32: "dc",
|
|
4656
|
+
bip44: 3,
|
|
4657
|
+
bip32: {
|
|
4658
|
+
public: 49990397,
|
|
4659
|
+
private: 49988504
|
|
4660
|
+
},
|
|
4661
|
+
pubKeyHash: 30,
|
|
4662
|
+
scriptHash: 22,
|
|
4663
|
+
wif: 158
|
|
4664
|
+
};
|
|
4665
|
+
|
|
4666
|
+
// src/dogecoin/utils-doge.ts
|
|
4667
|
+
var DogecoinUtils = class {
|
|
4668
|
+
/**
|
|
4669
|
+
* Build the PSBT from the transaction
|
|
4670
|
+
* @param tx utxoTx
|
|
4671
|
+
* @param _maximumFeeRate number (optional, currently unused)
|
|
4672
|
+
* @returns base64
|
|
4673
|
+
*/
|
|
4674
|
+
static buildPsbtToBase64(tx, _maximumFeeRate) {
|
|
4675
|
+
const psbt = new Psbt({ network });
|
|
4676
|
+
for (const input of tx.inputs) {
|
|
4677
|
+
const inputOptions = {
|
|
4678
|
+
hash: input.txId,
|
|
4679
|
+
index: input.vOut
|
|
4680
|
+
};
|
|
4681
|
+
if (input.nonWitnessUtxo) {
|
|
4682
|
+
inputOptions.nonWitnessUtxo = Buffer.from(input.nonWitnessUtxo, "hex");
|
|
4683
|
+
}
|
|
4684
|
+
psbt.addInput(inputOptions);
|
|
4685
|
+
}
|
|
4686
|
+
for (const output of tx.outputs) {
|
|
4687
|
+
psbt.addOutput({
|
|
4688
|
+
value: output.amount,
|
|
4689
|
+
address: output.address
|
|
4690
|
+
});
|
|
4691
|
+
}
|
|
4692
|
+
const psbtHex = psbt.toHex();
|
|
4693
|
+
return toBase64(fromHex3(psbtHex));
|
|
4694
|
+
}
|
|
4695
|
+
/**
|
|
4696
|
+
* Extract the transaction from the signed PSBT
|
|
4697
|
+
* @param signedPsbt base64
|
|
4698
|
+
* @param _maximumFeeRate number (optional, currently unused)
|
|
4699
|
+
* @returns transaction hex
|
|
4700
|
+
*/
|
|
4701
|
+
static extractPsbtTransaction(signedPsbt, _maximumFeeRate) {
|
|
4702
|
+
const signedPsbtHex = toHex3(fromBase64(signedPsbt));
|
|
4703
|
+
const psbt = Psbt.fromHex(signedPsbtHex, {
|
|
4704
|
+
network
|
|
4705
|
+
});
|
|
4706
|
+
const maximumFeeRate = _maximumFeeRate || 1e5;
|
|
4707
|
+
psbt.setMaximumFeeRate(maximumFeeRate);
|
|
4708
|
+
psbt.finalizeAllInputs();
|
|
4709
|
+
const transaction = psbt.extractTransaction();
|
|
4710
|
+
return transaction.toHex();
|
|
4711
|
+
}
|
|
4712
|
+
/**
|
|
4713
|
+
* Convert raw transaction hex to PSBT base64
|
|
4714
|
+
* This method converts an unsigned raw transaction to PSBT format.
|
|
4715
|
+
* Note: The rawTx should be an unsigned transaction, and the nonWitnessUtxo
|
|
4716
|
+
* for each input will need to be fetched separately from the blockchain.
|
|
4717
|
+
* @param rawTx hex string of the raw transaction
|
|
4718
|
+
* @returns base64 string of the PSBT
|
|
4719
|
+
*/
|
|
4720
|
+
static async rawTxToPsbtBase64(rawTx) {
|
|
4721
|
+
try {
|
|
4722
|
+
const cleanHex = rawTx.startsWith("0x") ? rawTx.slice(2) : rawTx;
|
|
4723
|
+
const transaction = Transaction.fromHex(cleanHex);
|
|
4724
|
+
const psbt = new Psbt({ network });
|
|
4725
|
+
for (let i = 0; i < transaction.ins.length; i++) {
|
|
4726
|
+
const input = transaction.ins[i];
|
|
4727
|
+
const hash = Buffer.from(input.hash).reverse().toString("hex");
|
|
4728
|
+
const index = input.index;
|
|
4729
|
+
const inputOptions = {
|
|
4730
|
+
hash,
|
|
4731
|
+
index,
|
|
4732
|
+
nonWitnessUtxo: input.script
|
|
4733
|
+
};
|
|
4734
|
+
psbt.addInput(inputOptions);
|
|
4735
|
+
}
|
|
4736
|
+
for (const output of transaction.outs) {
|
|
4737
|
+
try {
|
|
4738
|
+
const address$1 = address.fromOutputScript(output.script, network);
|
|
4739
|
+
psbt.addOutput({
|
|
4740
|
+
address: address$1,
|
|
4741
|
+
value: Number(output.value)
|
|
4742
|
+
});
|
|
4743
|
+
} catch (error) {
|
|
4744
|
+
psbt.addOutput({
|
|
4745
|
+
script: output.script,
|
|
4746
|
+
value: Number(output.value)
|
|
4747
|
+
});
|
|
4748
|
+
}
|
|
4749
|
+
}
|
|
4750
|
+
const psbtHex = psbt.toHex();
|
|
4751
|
+
return toBase64(fromHex3(psbtHex));
|
|
4752
|
+
} catch (error) {
|
|
4753
|
+
console.warn("rawTxToPsbtBase64 failed:", error);
|
|
4754
|
+
throw new Error(
|
|
4755
|
+
`Failed to convert raw transaction to PSBT: ${error instanceof Error ? error.message : String(error)}`
|
|
4756
|
+
);
|
|
4757
|
+
}
|
|
4758
|
+
}
|
|
4759
|
+
};
|
|
4760
|
+
var KOINU_PER_DOGE = new BigNumber(DECIMALS);
|
|
4761
|
+
function toSatoshi(bitcion) {
|
|
4762
|
+
try {
|
|
4763
|
+
const amount = new BigNumber(bitcion);
|
|
4764
|
+
if (amount.isNaN() || amount.isNegative()) {
|
|
4765
|
+
throw new Error("Invalid amount");
|
|
4766
|
+
}
|
|
4767
|
+
return amount.times(KOINU_PER_DOGE).integerValue(BigNumber.ROUND_DOWN).toNumber();
|
|
4768
|
+
} catch (error) {
|
|
4769
|
+
throw new Error(`toSatoshi failed: ${error.message}`);
|
|
4770
|
+
}
|
|
4771
|
+
}
|
|
4772
|
+
function toBitcoin(satoshis) {
|
|
4773
|
+
try {
|
|
4774
|
+
const amount = new BigNumber(satoshis);
|
|
4775
|
+
if (amount.isNaN() || amount.isNegative()) {
|
|
4776
|
+
throw new Error("Invalid Koinu amount");
|
|
4777
|
+
}
|
|
4778
|
+
return amount.dividedBy(KOINU_PER_DOGE).toNumber();
|
|
4779
|
+
} catch (error) {
|
|
4780
|
+
throw new Error(`toBitcoin failed: ${error.message}`);
|
|
4781
|
+
}
|
|
4782
|
+
}
|
|
4783
|
+
function addUsedUtxos(newUsedUtxos) {
|
|
4784
|
+
const usedUtxos = cache.get("UsedUtxos") || {};
|
|
4785
|
+
for (const txid in newUsedUtxos) {
|
|
4786
|
+
usedUtxos[txid] = 1;
|
|
4787
|
+
}
|
|
4788
|
+
cache.set("UsedUtxos", usedUtxos, false);
|
|
4789
|
+
}
|
|
4790
|
+
async function createPsbt({
|
|
4791
|
+
from,
|
|
4792
|
+
to,
|
|
4793
|
+
amount,
|
|
4794
|
+
fee,
|
|
4795
|
+
spendableUtxos
|
|
4796
|
+
}) {
|
|
4797
|
+
const utxos = spendableUtxos;
|
|
4798
|
+
if (!utxos || utxos.length === 0) {
|
|
4799
|
+
throw new Error("no spendable utxos");
|
|
4800
|
+
}
|
|
4801
|
+
const sendAmount = toSatoshi(amount);
|
|
4802
|
+
const sendCost = toSatoshi(fee);
|
|
4803
|
+
const totalNeeded = sendAmount + sendCost;
|
|
4804
|
+
const sortedUtxos = utxos.sort((a, b) => b.outputValue - a.outputValue);
|
|
4805
|
+
const selectedUtxos = [];
|
|
4806
|
+
let accumulatedAmount = 0;
|
|
4807
|
+
for (const utxo of sortedUtxos) {
|
|
4808
|
+
if (accumulatedAmount >= totalNeeded) break;
|
|
4809
|
+
selectedUtxos.push(utxo);
|
|
4810
|
+
accumulatedAmount += Number(utxo.outputValue);
|
|
4811
|
+
}
|
|
4812
|
+
if (accumulatedAmount < totalNeeded) {
|
|
4813
|
+
throw new Error("not enough funds to cover amount and fee");
|
|
4814
|
+
}
|
|
4815
|
+
const utxoDetailPromises = selectedUtxos.map(async (utxo) => {
|
|
4816
|
+
try {
|
|
4817
|
+
const utxoDetail = await getTxDetail(utxo.txid);
|
|
4818
|
+
return { utxo, utxoDetail };
|
|
4819
|
+
} catch (error) {
|
|
4820
|
+
return { utxo, utxoDetail: null };
|
|
4821
|
+
}
|
|
4822
|
+
});
|
|
4823
|
+
const utxoResults = await Promise.all(utxoDetailPromises);
|
|
4824
|
+
const inputs = [];
|
|
4825
|
+
const usingUtxos = {};
|
|
4826
|
+
let addedAmount = 0;
|
|
4827
|
+
for (const { utxo, utxoDetail } of utxoResults) {
|
|
4828
|
+
if (addedAmount >= totalNeeded) break;
|
|
4829
|
+
const { txid, vout, outputValue, address = from } = utxo;
|
|
4830
|
+
if (utxoDetail?.hex && !usingUtxos[txid]) {
|
|
4831
|
+
inputs.push({
|
|
4832
|
+
txId: txid,
|
|
4833
|
+
vOut: vout,
|
|
4834
|
+
amount: Number(outputValue),
|
|
4835
|
+
nonWitnessUtxo: utxoDetail.hex,
|
|
4836
|
+
address
|
|
4837
|
+
});
|
|
4838
|
+
usingUtxos[txid] = 1;
|
|
4839
|
+
addedAmount += Number(outputValue);
|
|
4840
|
+
}
|
|
4841
|
+
}
|
|
4842
|
+
if (addedAmount < totalNeeded) {
|
|
4843
|
+
throw new Error("not enough funds to cover amount and fee");
|
|
4844
|
+
}
|
|
4845
|
+
const outputs = [
|
|
4846
|
+
{
|
|
4847
|
+
address: to,
|
|
4848
|
+
amount: sendAmount
|
|
4849
|
+
}
|
|
4850
|
+
];
|
|
4851
|
+
const changeAmount = addedAmount - sendAmount - sendCost;
|
|
4852
|
+
if (changeAmount > 0) {
|
|
4853
|
+
outputs.push({
|
|
4854
|
+
address: from,
|
|
4855
|
+
amount: changeAmount
|
|
4856
|
+
});
|
|
4857
|
+
}
|
|
4858
|
+
const params = {
|
|
4859
|
+
address: from,
|
|
4860
|
+
inputs,
|
|
4861
|
+
outputs
|
|
4862
|
+
};
|
|
4863
|
+
const psbtBase64 = DogecoinUtils.buildPsbtToBase64(params);
|
|
4864
|
+
return { psbtBase64, usingUtxos };
|
|
4865
|
+
}
|
|
4866
|
+
var mydoge = axios.create({
|
|
4867
|
+
baseURL: MYDOGE_BASE_URL
|
|
4868
|
+
});
|
|
4869
|
+
var api = axios.create({
|
|
4870
|
+
baseURL: RPC_URL,
|
|
4871
|
+
timeout: RPC_TIMEOUT
|
|
4872
|
+
});
|
|
4873
|
+
async function getBalance(address) {
|
|
4874
|
+
if (!address) {
|
|
4875
|
+
return {
|
|
4876
|
+
address: "",
|
|
4877
|
+
balance: 0
|
|
4878
|
+
};
|
|
4879
|
+
}
|
|
4880
|
+
const path = `/address/${address}?page=1&pageSize=10`;
|
|
4881
|
+
const api2 = `${MYDOGE_BASE_URL}/wallet/info?route=` + encodeURIComponent(path);
|
|
4882
|
+
const res = await mydoge.get(api2);
|
|
4883
|
+
return res.data || {};
|
|
4884
|
+
}
|
|
4885
|
+
async function getTxDetail(txId) {
|
|
4886
|
+
if (!txId) {
|
|
4887
|
+
return {};
|
|
4888
|
+
}
|
|
4889
|
+
const path = `/tx/${txId}`;
|
|
4890
|
+
const api2 = `${MYDOGE_BASE_URL}/wallet/info?route=` + encodeURIComponent(path);
|
|
4891
|
+
const res = await mydoge.get(api2);
|
|
4892
|
+
return res.data || {};
|
|
4893
|
+
}
|
|
4894
|
+
var Drc20DetailsCacheKey = "Drc20Details";
|
|
4895
|
+
cache.get(Drc20DetailsCacheKey) || {};
|
|
4896
|
+
async function getUtxos(address, cursor, result, filter, tx = null) {
|
|
4897
|
+
const query = (await mydoge.get(`${MYDOGE_BASE_URL}/utxos/${address}?filter=${filter}${cursor ? `&cursor=${cursor}` : ""}`)).data;
|
|
4898
|
+
let { utxos } = query;
|
|
4899
|
+
if (tx) {
|
|
4900
|
+
utxos = utxos.filter((utxo) => utxo.txid === tx?.txid && utxo.vout === tx?.vout);
|
|
4901
|
+
}
|
|
4902
|
+
result.push(
|
|
4903
|
+
...utxos.map((i) => ({
|
|
4904
|
+
txid: i.txid,
|
|
4905
|
+
vout: i.vout,
|
|
4906
|
+
outputValue: i.satoshis,
|
|
4907
|
+
script: i.script_pubkey,
|
|
4908
|
+
...filter === "inscriptions"
|
|
4909
|
+
}))
|
|
4910
|
+
);
|
|
4911
|
+
if (result.length && tx) {
|
|
4912
|
+
return;
|
|
4913
|
+
}
|
|
4914
|
+
result = result.sort((a, b) => toBitcoin(b.outputValue) - toBitcoin(a.outputValue));
|
|
4915
|
+
if (query.next_cursor) {
|
|
4916
|
+
return getUtxos(address, query.next_cursor, result, filter, tx);
|
|
4917
|
+
}
|
|
4918
|
+
}
|
|
4919
|
+
async function getSpendableUtxos(address) {
|
|
4920
|
+
const utxos = [];
|
|
4921
|
+
await getUtxos(address, 0, utxos, "spendable");
|
|
4922
|
+
return utxos;
|
|
4923
|
+
}
|
|
4924
|
+
var DuneDetailsCacheKey = "DuneDetails";
|
|
4925
|
+
cache.get(DuneDetailsCacheKey) || {};
|
|
4926
|
+
var sendDogeTx = async (rawTx) => {
|
|
4927
|
+
try {
|
|
4928
|
+
const res = await api.post("/tx/send", { rawTx });
|
|
4929
|
+
return res.data;
|
|
4930
|
+
} catch (e) {
|
|
4931
|
+
if (typeof e?.response?.data === "string") return Promise.reject(e?.response?.data);
|
|
4932
|
+
else return Promise.reject(e.message);
|
|
4933
|
+
}
|
|
4934
|
+
};
|
|
4935
|
+
|
|
4936
|
+
// src/dogecoin/service.ts
|
|
4937
|
+
var DogecoinService = class _DogecoinService extends BaseService {
|
|
4938
|
+
static instance;
|
|
4939
|
+
chainType;
|
|
4940
|
+
constructor(chainType, accountInfo, tomoAppInfo) {
|
|
4941
|
+
super(tomoAppInfo, accountInfo);
|
|
4942
|
+
this.chainType = chainType;
|
|
4943
|
+
}
|
|
4944
|
+
//singleton
|
|
4945
|
+
static getInstance(chainType, accountInfo, tomoAppInfo) {
|
|
4946
|
+
if (!_DogecoinService.instance) {
|
|
4947
|
+
_DogecoinService.instance = new _DogecoinService(chainType, accountInfo, tomoAppInfo);
|
|
4948
|
+
}
|
|
4949
|
+
return _DogecoinService.instance;
|
|
4950
|
+
}
|
|
4951
|
+
async requestAccounts() {
|
|
4952
|
+
const addresses = await this.accountInfo.getCurrent();
|
|
4953
|
+
const { publicKey, address } = addresses?.[0] || {};
|
|
4954
|
+
if (!address) {
|
|
4955
|
+
throw new Error("address is not set");
|
|
4956
|
+
}
|
|
4957
|
+
const { balance = 0 } = await getBalance(address);
|
|
4958
|
+
return {
|
|
4959
|
+
address,
|
|
4960
|
+
balance,
|
|
4961
|
+
approved: true,
|
|
4962
|
+
publicKey
|
|
4963
|
+
};
|
|
4964
|
+
}
|
|
4965
|
+
async getAccounts() {
|
|
4966
|
+
const accounts = await this.accountInfo.getCurrent();
|
|
4967
|
+
return accounts.map((account) => account.address);
|
|
4968
|
+
}
|
|
4969
|
+
async getConnectionStatus() {
|
|
4970
|
+
const addresses = await this.accountInfo.getCurrent();
|
|
4971
|
+
const { address } = addresses?.[0] || {};
|
|
4972
|
+
if (!address) {
|
|
4973
|
+
throw new Error("address is not set");
|
|
4974
|
+
}
|
|
4975
|
+
return {
|
|
4976
|
+
connected: true,
|
|
4977
|
+
address,
|
|
4978
|
+
selectedWalletAddress: address
|
|
4979
|
+
};
|
|
4980
|
+
}
|
|
4981
|
+
async getBalance() {
|
|
4982
|
+
const addresses = await this.accountInfo.getCurrent();
|
|
4983
|
+
const { address } = addresses?.[0] || {};
|
|
4984
|
+
if (!address) {
|
|
4985
|
+
throw new Error("address is not set");
|
|
4986
|
+
}
|
|
4987
|
+
const { balance = 0 } = await getBalance(address);
|
|
4988
|
+
return {
|
|
4989
|
+
address,
|
|
4990
|
+
balance
|
|
4991
|
+
};
|
|
4992
|
+
}
|
|
4993
|
+
async signMessage({ message, type }) {
|
|
4994
|
+
if (type) {
|
|
4995
|
+
throw new Error("bip322simple not support.");
|
|
4996
|
+
}
|
|
4997
|
+
const signature = await this.accountInfo.signMessage(message);
|
|
4998
|
+
return {
|
|
4999
|
+
signedMessage: signature
|
|
5000
|
+
};
|
|
5001
|
+
}
|
|
5002
|
+
async requestSignedMessage({
|
|
5003
|
+
message,
|
|
5004
|
+
type
|
|
5005
|
+
}) {
|
|
5006
|
+
return await this.signMessage({
|
|
5007
|
+
message,
|
|
5008
|
+
type
|
|
5009
|
+
});
|
|
5010
|
+
}
|
|
5011
|
+
async requestDecryptedMessage({ message }) {
|
|
5012
|
+
try {
|
|
5013
|
+
if (!this.accountInfo?.decryptedMessage) {
|
|
5014
|
+
throw new Error("decryptedMessage is not supported");
|
|
5015
|
+
}
|
|
5016
|
+
const unsignRes = await this.accountInfo?.decryptedMessage(message);
|
|
5017
|
+
const { text = "" } = JSON.parse(unsignRes);
|
|
5018
|
+
return {
|
|
5019
|
+
decryptedMessage: text
|
|
5020
|
+
};
|
|
5021
|
+
} catch (err) {
|
|
5022
|
+
throw new Error("requestDecryptedMessage err:" + JSON.stringify(err));
|
|
5023
|
+
}
|
|
5024
|
+
}
|
|
5025
|
+
async _queryGasInfo(txData) {
|
|
5026
|
+
const { chainId, amount = 0, decimals = 8 } = txData;
|
|
5027
|
+
const gasLimitParam = {
|
|
5028
|
+
from: txData.from,
|
|
5029
|
+
to: txData.to,
|
|
5030
|
+
value: toHex(parseUnits(amount.toString(), decimals))
|
|
5031
|
+
};
|
|
5032
|
+
const queryGasParams = {
|
|
5033
|
+
chainIndex: Number(chainId || BaseConfig2.chainId),
|
|
5034
|
+
callData: "0x",
|
|
5035
|
+
gasLimitParam,
|
|
5036
|
+
addressList: [txData.from]
|
|
5037
|
+
};
|
|
5038
|
+
const {
|
|
5039
|
+
data: gasInfo,
|
|
5040
|
+
success,
|
|
5041
|
+
message
|
|
5042
|
+
} = await this.transactions.queryGasInfo({
|
|
5043
|
+
chainType: this.chainType,
|
|
5044
|
+
params: queryGasParams
|
|
5045
|
+
});
|
|
5046
|
+
if (!success) {
|
|
5047
|
+
console.error("queryGasInfo doge", success, txData, queryGasParams, gasInfo);
|
|
5048
|
+
const { gasFee } = BaseConfig2;
|
|
5049
|
+
return {
|
|
5050
|
+
success: true,
|
|
5051
|
+
gasFee: gasFee.toString()
|
|
5052
|
+
};
|
|
5053
|
+
}
|
|
5054
|
+
const { baseFee = 1, gasLimit = 1 } = gasInfo;
|
|
5055
|
+
const calcFee = (feeLevel) => {
|
|
5056
|
+
const gasFee = new BigNumber(gasInfo[feeLevel] || baseFee).times(gasLimit);
|
|
5057
|
+
return toBitcoin(gasFee.toNumber());
|
|
5058
|
+
};
|
|
5059
|
+
const fees = {
|
|
5060
|
+
low: calcFee("priorityFeeLow"),
|
|
5061
|
+
medium: calcFee("priorityFeeMedium"),
|
|
5062
|
+
high: calcFee("priorityFeeHigh")
|
|
5063
|
+
};
|
|
5064
|
+
return {
|
|
5065
|
+
success: true,
|
|
5066
|
+
fees,
|
|
5067
|
+
gasFee: fees.high
|
|
5068
|
+
};
|
|
5069
|
+
}
|
|
5070
|
+
async requestPsbt({
|
|
5071
|
+
rawTx,
|
|
5072
|
+
signOnly
|
|
5073
|
+
}) {
|
|
5074
|
+
const psbtBase64 = await DogecoinUtils.rawTxToPsbtBase64(rawTx);
|
|
5075
|
+
const signedPsbt = await this.accountInfo.signTransaction(JSON.stringify({ psbtBase64 }));
|
|
5076
|
+
if (!signedPsbt) {
|
|
5077
|
+
return null;
|
|
5078
|
+
}
|
|
5079
|
+
const signedRawTx = DogecoinUtils.extractPsbtTransaction(signedPsbt, 1e5);
|
|
5080
|
+
if (signOnly) {
|
|
5081
|
+
return {
|
|
5082
|
+
signedRawTx
|
|
5083
|
+
};
|
|
5084
|
+
}
|
|
5085
|
+
const { txid = "" } = await sendDogeTx(signedRawTx);
|
|
5086
|
+
return {
|
|
5087
|
+
txId: txid,
|
|
5088
|
+
signedRawTx
|
|
5089
|
+
};
|
|
5090
|
+
}
|
|
5091
|
+
async requestTransaction(txData) {
|
|
5092
|
+
const spendableUtxos = txData?.spendableUtxos;
|
|
5093
|
+
if (txData.amountMismatch) {
|
|
5094
|
+
throw new Error("balance_insufficient");
|
|
5095
|
+
}
|
|
5096
|
+
if (!spendableUtxos || spendableUtxos?.length === 0) {
|
|
5097
|
+
txData.spendableUtxos = await getSpendableUtxos(txData.from);
|
|
5098
|
+
}
|
|
5099
|
+
const { psbtBase64, usingUtxos } = await createPsbt(txData);
|
|
5100
|
+
const signedPsbt = await this.accountInfo.signTransaction(JSON.stringify({ psbtBase64 }));
|
|
5101
|
+
const signedTx = DogecoinUtils.extractPsbtTransaction(signedPsbt, 1e5);
|
|
5102
|
+
if (signedTx === "") {
|
|
5103
|
+
throw new Error("Error: sign transaction err.");
|
|
5104
|
+
}
|
|
5105
|
+
try {
|
|
5106
|
+
const { txid } = await sendDogeTx(signedTx);
|
|
5107
|
+
addUsedUtxos(usingUtxos);
|
|
5108
|
+
return { txId: txid };
|
|
5109
|
+
} catch (err) {
|
|
5110
|
+
throw new Error("Error: send transaction err." + JSON.stringify(err));
|
|
5111
|
+
}
|
|
5112
|
+
}
|
|
5113
|
+
async getTransactionStatus({ txId }) {
|
|
5114
|
+
const transaction = await getTxDetail(txId);
|
|
5115
|
+
if (!transaction?.txid) {
|
|
5116
|
+
return null;
|
|
5117
|
+
}
|
|
5118
|
+
return {
|
|
5119
|
+
txId: transaction.txid,
|
|
5120
|
+
confirmations: transaction.confirmations,
|
|
5121
|
+
status: transaction.confirmations > 0 ? "confirmed" : "pending",
|
|
5122
|
+
dogeAmount: transaction.vout[0]?.value,
|
|
5123
|
+
blockTime: transaction.blockTime,
|
|
5124
|
+
address: transaction.vout[0]?.addresses[0]
|
|
5125
|
+
};
|
|
5126
|
+
}
|
|
5127
|
+
};
|
|
4622
5128
|
var TomoWallet = class _TomoWallet extends BaseService {
|
|
4623
5129
|
static instance;
|
|
4624
5130
|
walletId;
|
|
@@ -4638,8 +5144,8 @@ var TomoWallet = class _TomoWallet extends BaseService {
|
|
|
4638
5144
|
}
|
|
4639
5145
|
async getChainInfo(chainType, chainId) {
|
|
4640
5146
|
this.networks.setChainType(chainType);
|
|
4641
|
-
const
|
|
4642
|
-
return
|
|
5147
|
+
const network2 = await this.networks.getNetworkByChainId(chainId);
|
|
5148
|
+
return network2;
|
|
4643
5149
|
}
|
|
4644
5150
|
//evm chains
|
|
4645
5151
|
async isChainSupported(chainType, chainId) {
|
|
@@ -4706,8 +5212,8 @@ var TomoWallet = class _TomoWallet extends BaseService {
|
|
|
4706
5212
|
// src/index.ts
|
|
4707
5213
|
var ChainTypeServices = {
|
|
4708
5214
|
[ChainTypes.EVM]: EvmService,
|
|
4709
|
-
[ChainTypes.SOL]: SolanaService
|
|
4710
|
-
|
|
5215
|
+
[ChainTypes.SOL]: SolanaService,
|
|
5216
|
+
[ChainTypes.DOGE]: DogecoinService
|
|
4711
5217
|
};
|
|
4712
5218
|
|
|
4713
|
-
export { AccountType, ChainTypeServices, EvmService, SolanaService, TomoWallet, TxTypes };
|
|
5219
|
+
export { AccountType, ChainTypeServices, DogecoinService, EvmService, SolanaService, TomoWallet, TxTypes };
|