@tomo-inc/chains-service 0.0.7 → 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.cjs
CHANGED
|
@@ -7,6 +7,7 @@ var axios = require('axios');
|
|
|
7
7
|
var CryptoJS = require('crypto-js');
|
|
8
8
|
var splToken = require('@solana/spl-token');
|
|
9
9
|
var web3_js = require('@solana/web3.js');
|
|
10
|
+
var bitcoinjsLib = require('bitcoinjs-lib');
|
|
10
11
|
|
|
11
12
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
12
13
|
|
|
@@ -2804,18 +2805,18 @@ var Networks = class {
|
|
|
2804
2805
|
return networks;
|
|
2805
2806
|
}
|
|
2806
2807
|
async getNetworkByChainId(chainId) {
|
|
2807
|
-
const
|
|
2808
|
-
if (!
|
|
2808
|
+
const network2 = await this.networkAPIs.getNetworkByChainId(chainId);
|
|
2809
|
+
if (!network2) {
|
|
2809
2810
|
throw new Error("Network not found");
|
|
2810
2811
|
}
|
|
2811
|
-
return
|
|
2812
|
+
return network2;
|
|
2812
2813
|
}
|
|
2813
2814
|
async getNetworkByChainIndex(chainIndex) {
|
|
2814
|
-
const
|
|
2815
|
-
if (!
|
|
2815
|
+
const network2 = await this.networkAPIs.getNetworkByChainIndex(chainIndex);
|
|
2816
|
+
if (!network2) {
|
|
2816
2817
|
throw new Error("Network not found");
|
|
2817
2818
|
}
|
|
2818
|
-
return
|
|
2819
|
+
return network2;
|
|
2819
2820
|
}
|
|
2820
2821
|
async getCurrentNetwork() {
|
|
2821
2822
|
const chainType = this.chainType;
|
|
@@ -2838,8 +2839,8 @@ var Tokens = class {
|
|
|
2838
2839
|
constructor(tokenService) {
|
|
2839
2840
|
this.tokenAPIs = tokenService;
|
|
2840
2841
|
}
|
|
2841
|
-
async searchTokens({ chainIndex,
|
|
2842
|
-
const { data: tokens = [] } = await this.tokenAPIs.queryRemoteTokens({ keyword
|
|
2842
|
+
async searchTokens({ chainIndex, keyword }) {
|
|
2843
|
+
const { data: tokens = [] } = await this.tokenAPIs.queryRemoteTokens({ keyword, chainIndex });
|
|
2843
2844
|
return tokens;
|
|
2844
2845
|
}
|
|
2845
2846
|
// public async addToken(tokenInfo: Omit<TokenInfo, "id">): Promise<TokenInfo> {
|
|
@@ -2847,10 +2848,8 @@ var Tokens = class {
|
|
|
2847
2848
|
// return tokenInfoData;
|
|
2848
2849
|
// }
|
|
2849
2850
|
async getTokenInfo({ address, chainIndex }) {
|
|
2850
|
-
const {
|
|
2851
|
-
|
|
2852
|
-
} = await this.tokenAPIs.getTokenInfo({ address, chainIndex });
|
|
2853
|
-
return tokenInfo;
|
|
2851
|
+
const res = await this.tokenAPIs.getTokenInfo({ address, chainIndex });
|
|
2852
|
+
return res?.data?.data;
|
|
2854
2853
|
}
|
|
2855
2854
|
async getTokenRiskInfo(_params) {
|
|
2856
2855
|
const { data: tokenRiskInfo } = await this.tokenAPIs.getTokenRisk(_params);
|
|
@@ -2980,7 +2979,7 @@ var BasePublicService = class {
|
|
|
2980
2979
|
this.apiBase = publicApiBase;
|
|
2981
2980
|
this.tomoAppInfo = tomoAppInfo;
|
|
2982
2981
|
[this.tokenApi, this.txApi, this.walletApi].map(
|
|
2983
|
-
(
|
|
2982
|
+
(api2, i) => api2.interceptors.request.use((params) => {
|
|
2984
2983
|
const { tokenBaseUrl, txBaseUrl, walletBaseUrl } = publicApiBase;
|
|
2985
2984
|
params.baseURL = [tokenBaseUrl, txBaseUrl, walletBaseUrl][i];
|
|
2986
2985
|
return signRequest(params, tomoAppInfo.tomoClientId, tomoAppInfo);
|
|
@@ -3021,10 +3020,15 @@ var TokenAPIs = class _TokenAPIs extends BasePublicService {
|
|
|
3021
3020
|
}
|
|
3022
3021
|
}
|
|
3023
3022
|
async getTokenRisk(params) {
|
|
3024
|
-
if (typeof params.chainIndex !== "number" || !params.
|
|
3023
|
+
if (typeof params.chainIndex !== "number" || !params.address) {
|
|
3025
3024
|
throw new Error("chainName or tokenAddress is required");
|
|
3026
3025
|
}
|
|
3027
|
-
const res = await this.tokenApi.post("/v1/market/risk/details", [
|
|
3026
|
+
const res = await this.tokenApi.post("/v1/market/risk/details", [
|
|
3027
|
+
{
|
|
3028
|
+
chainIndex: params.chainIndex,
|
|
3029
|
+
tokenAddress: params.address
|
|
3030
|
+
}
|
|
3031
|
+
]);
|
|
3028
3032
|
return {
|
|
3029
3033
|
success: res?.data?.code === "0",
|
|
3030
3034
|
message: res?.data?.msg,
|
|
@@ -3112,10 +3116,10 @@ var TokenAPIs = class _TokenAPIs extends BasePublicService {
|
|
|
3112
3116
|
}
|
|
3113
3117
|
}
|
|
3114
3118
|
async getTokenDetail(params) {
|
|
3115
|
-
const { chainIndex,
|
|
3119
|
+
const { chainIndex, address } = params;
|
|
3116
3120
|
const res = await this.tokenApi.get(`/v1/market/token/detail`, {
|
|
3117
3121
|
params: {
|
|
3118
|
-
tokenAddress,
|
|
3122
|
+
tokenAddress: address,
|
|
3119
3123
|
chainIndex
|
|
3120
3124
|
}
|
|
3121
3125
|
});
|
|
@@ -3267,12 +3271,26 @@ var loadNetworks = (WALLET_DOMAIN) => {
|
|
|
3267
3271
|
supportHistory: false
|
|
3268
3272
|
},
|
|
3269
3273
|
{
|
|
3270
|
-
chainId:
|
|
3271
|
-
chainIndex:
|
|
3272
|
-
name: "
|
|
3273
|
-
chainName: "
|
|
3274
|
+
chainId: 26888,
|
|
3275
|
+
chainIndex: 2688800,
|
|
3276
|
+
name: "ABCORE_TESTNET",
|
|
3277
|
+
chainName: "AB Core Testnet",
|
|
3278
|
+
rpcUrls: ["https://rpc.core.testnet.ab.org"],
|
|
3279
|
+
blockExplorerUrl: "https://explorer.core.testnet.ab.org",
|
|
3280
|
+
platformType: "EVM",
|
|
3281
|
+
isTestnet: true,
|
|
3282
|
+
icon: "/assets/ab.svg",
|
|
3283
|
+
supportSwap: true,
|
|
3284
|
+
supportGift: false,
|
|
3285
|
+
supportHistory: true
|
|
3286
|
+
},
|
|
3287
|
+
{
|
|
3288
|
+
chainId: 6281971,
|
|
3289
|
+
chainIndex: 628197100,
|
|
3290
|
+
name: "DOGEOS_TESTNET",
|
|
3291
|
+
chainName: "DogeOS Testnet",
|
|
3274
3292
|
rpcUrls: [`${WALLET_DOMAIN}/rpc/v1/doge_test`],
|
|
3275
|
-
blockExplorerUrl: "https://
|
|
3293
|
+
blockExplorerUrl: "https://rpc.testnet.dogeos.com",
|
|
3276
3294
|
platformType: "EVM",
|
|
3277
3295
|
isTestnet: true,
|
|
3278
3296
|
icon: "/assets/dogeos.svg",
|
|
@@ -3894,7 +3912,7 @@ var BaseService = class {
|
|
|
3894
3912
|
}
|
|
3895
3913
|
const baseUrlConfig = CONFIG[tomoAppInfo.tomoStage];
|
|
3896
3914
|
const { tokenAPIs, transactionAPIs, networkAPIs } = tomoPublicApiService(baseUrlConfig, tomoAppInfo);
|
|
3897
|
-
this.accountInfo = accountInfo;
|
|
3915
|
+
this.accountInfo = accountInfo || null;
|
|
3898
3916
|
this.networks = new Networks(networkAPIs);
|
|
3899
3917
|
this.tokens = new Tokens(tokenAPIs);
|
|
3900
3918
|
this.transactions = new Transactions(transactionAPIs);
|
|
@@ -3904,8 +3922,8 @@ var BaseService = class {
|
|
|
3904
3922
|
this.approveParams = params;
|
|
3905
3923
|
}
|
|
3906
3924
|
};
|
|
3907
|
-
function getRPCClient(
|
|
3908
|
-
const { chainId, name, rpcUrls, nativeCurrencyDecimals, nativeCurrencyName, nativeCurrencySymbol } =
|
|
3925
|
+
function getRPCClient(network2) {
|
|
3926
|
+
const { chainId, name, rpcUrls, nativeCurrencyDecimals, nativeCurrencyName, nativeCurrencySymbol } = network2;
|
|
3909
3927
|
const myCustomChain = {
|
|
3910
3928
|
id: Number(chainId) || chainId,
|
|
3911
3929
|
name,
|
|
@@ -3960,8 +3978,8 @@ var TxTypes = /* @__PURE__ */ ((TxTypes2) => {
|
|
|
3960
3978
|
})(TxTypes || {});
|
|
3961
3979
|
|
|
3962
3980
|
// src/evm/utils.ts
|
|
3963
|
-
var isEvmChain = (
|
|
3964
|
-
return
|
|
3981
|
+
var isEvmChain = (network2) => {
|
|
3982
|
+
return network2 && network2?.platformType === "EVM";
|
|
3965
3983
|
};
|
|
3966
3984
|
var getAllTypeChainIds = ({ chainId, chainType }) => {
|
|
3967
3985
|
if (viem.isHex(chainId)) {
|
|
@@ -4053,7 +4071,7 @@ var EvmService = class _EvmService extends BaseService {
|
|
|
4053
4071
|
}
|
|
4054
4072
|
async personal_sign([message, address]) {
|
|
4055
4073
|
const accounts = await this.accountInfo.getCurrent();
|
|
4056
|
-
if (accounts[0].address
|
|
4074
|
+
if (!viem.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.signMessage(message);
|
|
@@ -4061,7 +4079,7 @@ var EvmService = class _EvmService extends BaseService {
|
|
|
4061
4079
|
}
|
|
4062
4080
|
async eth_signTypedData_v4([address, typedData]) {
|
|
4063
4081
|
const accounts = await this.accountInfo.getCurrent();
|
|
4064
|
-
if (accounts[0].address
|
|
4082
|
+
if (!viem.isAddressEqual(accounts[0].address, address)) {
|
|
4065
4083
|
throw new Error("address is not the current account");
|
|
4066
4084
|
}
|
|
4067
4085
|
const signature = await this.accountInfo.signTypedData(typedData);
|
|
@@ -4069,7 +4087,7 @@ var EvmService = class _EvmService extends BaseService {
|
|
|
4069
4087
|
}
|
|
4070
4088
|
async eth_getBalance([address, type]) {
|
|
4071
4089
|
const accounts = await this.accountInfo.getCurrent();
|
|
4072
|
-
if (accounts[0].address
|
|
4090
|
+
if (!viem.isAddressEqual(accounts[0].address, address)) {
|
|
4073
4091
|
throw new Error("address is not the current account");
|
|
4074
4092
|
}
|
|
4075
4093
|
if (type !== "latest") {
|
|
@@ -4113,8 +4131,8 @@ var EvmService = class _EvmService extends BaseService {
|
|
|
4113
4131
|
});
|
|
4114
4132
|
if (!success) {
|
|
4115
4133
|
console.error("queryGasInfo evm", txData, queryGasParams, message, gasInfo);
|
|
4116
|
-
const
|
|
4117
|
-
const { gasFee } =
|
|
4134
|
+
const BaseConfig3 = walletUtils.SupportedChainTypes[walletUtils.ChainTypes.EVM];
|
|
4135
|
+
const { gasFee } = BaseConfig3;
|
|
4118
4136
|
return {
|
|
4119
4137
|
success: true,
|
|
4120
4138
|
gasFee: gasFee.toString()
|
|
@@ -4146,51 +4164,6 @@ var EvmService = class _EvmService extends BaseService {
|
|
|
4146
4164
|
}
|
|
4147
4165
|
};
|
|
4148
4166
|
}
|
|
4149
|
-
async eth_estimateGas(txs) {
|
|
4150
|
-
const { from, to, value = "0x1" } = txs[0] || {};
|
|
4151
|
-
const accounts = await this.accountInfo.getCurrent();
|
|
4152
|
-
if (accounts[0].address !== from) {
|
|
4153
|
-
throw new Error("address is not the current account");
|
|
4154
|
-
}
|
|
4155
|
-
if (!to) {
|
|
4156
|
-
throw new Error("to is not set");
|
|
4157
|
-
}
|
|
4158
|
-
const chainId = txs[0]?.chainId || await this.eth_chainId();
|
|
4159
|
-
const queryGasParams = {
|
|
4160
|
-
chainIndex: Number(chainId),
|
|
4161
|
-
callData: "0x",
|
|
4162
|
-
gasLimitParam: {
|
|
4163
|
-
from,
|
|
4164
|
-
to,
|
|
4165
|
-
value
|
|
4166
|
-
},
|
|
4167
|
-
addressList: [from]
|
|
4168
|
-
};
|
|
4169
|
-
const chainType = this.chainType;
|
|
4170
|
-
const {
|
|
4171
|
-
data: gasInfo,
|
|
4172
|
-
success,
|
|
4173
|
-
message
|
|
4174
|
-
} = await this.transactions.queryGasInfo({
|
|
4175
|
-
chainType,
|
|
4176
|
-
params: queryGasParams
|
|
4177
|
-
});
|
|
4178
|
-
if (!success) {
|
|
4179
|
-
console.error("queryGasInfo evm", txs, message, gasInfo);
|
|
4180
|
-
const { gasFee } = walletUtils.SupportedChainTypes[chainType];
|
|
4181
|
-
return gasFee.toString();
|
|
4182
|
-
}
|
|
4183
|
-
const res = getAllTypeChainIds({ chainId, chainType });
|
|
4184
|
-
const { nativeCurrencyDecimals } = await this.networks.getNetworkByChainId(res.chainId);
|
|
4185
|
-
const { baseFee = 1, gasLimit = 0 } = gasInfo;
|
|
4186
|
-
const baseFeeBN = new Bignumber.BigNumber(baseFee);
|
|
4187
|
-
const calcFee = (feeLevel) => {
|
|
4188
|
-
const fee = baseFeeBN.plus(gasInfo[feeLevel] || 0);
|
|
4189
|
-
const gasFee = fee.times(gasLimit);
|
|
4190
|
-
return viem.toHex(BigInt(gasFee.toNumber()), nativeCurrencyDecimals);
|
|
4191
|
-
};
|
|
4192
|
-
return calcFee("priorityFeeMedium");
|
|
4193
|
-
}
|
|
4194
4167
|
async createPublicClient({ chainId, rpcUrl }) {
|
|
4195
4168
|
if (rpcUrl) {
|
|
4196
4169
|
return viem.createPublicClient({
|
|
@@ -4212,6 +4185,26 @@ var EvmService = class _EvmService extends BaseService {
|
|
|
4212
4185
|
transport: viem.http(rpcUrl)
|
|
4213
4186
|
});
|
|
4214
4187
|
}
|
|
4188
|
+
async eth_estimateGas(txs) {
|
|
4189
|
+
const { from, to, value = "0x1", chainId } = txs[0] || {};
|
|
4190
|
+
const accounts = await this.accountInfo.getCurrent();
|
|
4191
|
+
if (accounts[0].address !== from) {
|
|
4192
|
+
throw new Error("address is not the current account");
|
|
4193
|
+
}
|
|
4194
|
+
if (!to) {
|
|
4195
|
+
throw new Error("to is not set");
|
|
4196
|
+
}
|
|
4197
|
+
try {
|
|
4198
|
+
const rpcClient = await this.createPublicClient({ chainId: chainId?.toString() });
|
|
4199
|
+
const gas = await rpcClient.estimateGas({ account: from, to, value: viem.hexToBigInt(value) });
|
|
4200
|
+
return gas;
|
|
4201
|
+
} catch (error) {
|
|
4202
|
+
console.warn("Failed to estimate gas:", error);
|
|
4203
|
+
const BaseConfig3 = walletUtils.SupportedChainTypes[walletUtils.ChainTypes.EVM];
|
|
4204
|
+
const { gasFee } = BaseConfig3;
|
|
4205
|
+
return viem.numberToHex(viem.parseUnits(gasFee.toString(), 18));
|
|
4206
|
+
}
|
|
4207
|
+
}
|
|
4215
4208
|
// Get nonce for current account
|
|
4216
4209
|
async eth_getTransactionCount([address, type]) {
|
|
4217
4210
|
const accounts = await this.accountInfo.getCurrent();
|
|
@@ -4240,30 +4233,35 @@ var EvmService = class _EvmService extends BaseService {
|
|
|
4240
4233
|
nonce: "number",
|
|
4241
4234
|
maxPriorityFeePerGas: "bigint",
|
|
4242
4235
|
maxFeePerGas: "bigint",
|
|
4243
|
-
|
|
4236
|
+
gasPrice: "bigint",
|
|
4244
4237
|
gas: "bigint"
|
|
4245
4238
|
};
|
|
4246
|
-
|
|
4247
|
-
|
|
4248
|
-
txData = { ...txData, gas, gasLimit: gas };
|
|
4239
|
+
const txData = txParams?.[0];
|
|
4240
|
+
txData.gas = txData?.gas || txData?.gasLimit;
|
|
4249
4241
|
txData.data = txData.data || "0x";
|
|
4242
|
+
txData.value = txData.value || "0x";
|
|
4243
|
+
txData.nonce = txData.nonce || "0x0";
|
|
4244
|
+
if (!txData?.gas || !txData?.to || !txData?.chainId) {
|
|
4245
|
+
throw new Error("gas or to or chainId is not set");
|
|
4246
|
+
}
|
|
4250
4247
|
const accounts = await this.accountInfo.getCurrent();
|
|
4251
4248
|
const address = accounts[0].address;
|
|
4252
|
-
if (txData?.from && txData?.from
|
|
4249
|
+
if (txData?.from && !viem.isAddressEqual(txData?.from, address)) {
|
|
4253
4250
|
console.error("eth_signTransaction error data: from is not the current account", txData);
|
|
4254
4251
|
throw new Error(`eth_signTransaction error data: from is not the current account`);
|
|
4255
4252
|
}
|
|
4256
4253
|
delete txData?.from;
|
|
4254
|
+
delete txData?.gasLimit;
|
|
4257
4255
|
const preparedTx = {
|
|
4258
|
-
|
|
4259
|
-
gas: txData?.gasLimit,
|
|
4260
|
-
account: address
|
|
4256
|
+
gas: txData?.gas
|
|
4261
4257
|
};
|
|
4262
4258
|
for (const key in preparedTxPropsType) {
|
|
4263
|
-
if (
|
|
4264
|
-
|
|
4259
|
+
if (txData?.[key] && viem.isHex(txData?.[key])) {
|
|
4260
|
+
preparedTx[key] = preparedTxPropsType[key] === "number" ? viem.fromHex(txData[key], "number") : txData[key];
|
|
4265
4261
|
}
|
|
4266
|
-
|
|
4262
|
+
}
|
|
4263
|
+
if (txData?.type !== "legacy") {
|
|
4264
|
+
delete preparedTx.gasPrice;
|
|
4267
4265
|
}
|
|
4268
4266
|
try {
|
|
4269
4267
|
const serializedTransaction = await this.accountInfo.signTransaction(
|
|
@@ -4386,6 +4384,34 @@ async function createTokenLegacyTransaction2({
|
|
|
4386
4384
|
}
|
|
4387
4385
|
|
|
4388
4386
|
// src/dogecoin/base.ts
|
|
4387
|
+
function fromHex3(hex) {
|
|
4388
|
+
const cleanHex = hex.startsWith("0x") ? hex.slice(2) : hex;
|
|
4389
|
+
const paddedHex = cleanHex.length % 2 === 0 ? cleanHex : "0" + cleanHex;
|
|
4390
|
+
const bytes = new Uint8Array(paddedHex.length / 2);
|
|
4391
|
+
for (let i = 0; i < paddedHex.length; i += 2) {
|
|
4392
|
+
bytes[i / 2] = parseInt(paddedHex.substr(i, 2), 16);
|
|
4393
|
+
}
|
|
4394
|
+
return bytes;
|
|
4395
|
+
}
|
|
4396
|
+
function toHex3(data) {
|
|
4397
|
+
if (typeof data === "string") {
|
|
4398
|
+
return data.startsWith("0x") ? data.slice(2) : data;
|
|
4399
|
+
}
|
|
4400
|
+
const buffer = Buffer.isBuffer(data) ? data : Buffer.from(data);
|
|
4401
|
+
return buffer.toString("hex");
|
|
4402
|
+
}
|
|
4403
|
+
function toBase64(data) {
|
|
4404
|
+
if (typeof data === "string") {
|
|
4405
|
+
const buffer2 = Buffer.from(data, "hex");
|
|
4406
|
+
return buffer2.toString("base64");
|
|
4407
|
+
}
|
|
4408
|
+
const buffer = Buffer.isBuffer(data) ? data : Buffer.from(data);
|
|
4409
|
+
return buffer.toString("base64");
|
|
4410
|
+
}
|
|
4411
|
+
function fromBase64(base64) {
|
|
4412
|
+
const buffer = Buffer.from(base64, "base64");
|
|
4413
|
+
return new Uint8Array(buffer);
|
|
4414
|
+
}
|
|
4389
4415
|
function toBase58(data) {
|
|
4390
4416
|
throw new Error("toBase58 requires bs58 package. Install it: pnpm add bs58");
|
|
4391
4417
|
}
|
|
@@ -4422,11 +4448,11 @@ var SolanaService = class _SolanaService extends BaseService {
|
|
|
4422
4448
|
return await this.accountInfo.getCurrent();
|
|
4423
4449
|
}
|
|
4424
4450
|
async getAccount() {
|
|
4425
|
-
const { currentAddress, publicKey } = await this.accountInfo.
|
|
4451
|
+
const { address: currentAddress, publicKey } = await this.accountInfo.getCurrent();
|
|
4426
4452
|
return { publicKey: publicKey || currentAddress, address: currentAddress };
|
|
4427
4453
|
}
|
|
4428
4454
|
async signMessage(params) {
|
|
4429
|
-
const { currentAddress, publicKey } = await this.accountInfo.
|
|
4455
|
+
const { address: currentAddress, publicKey } = await this.accountInfo.getCurrent();
|
|
4430
4456
|
const { message } = params;
|
|
4431
4457
|
const signature = await this.accountInfo.signMessage(message);
|
|
4432
4458
|
return {
|
|
@@ -4436,7 +4462,7 @@ var SolanaService = class _SolanaService extends BaseService {
|
|
|
4436
4462
|
};
|
|
4437
4463
|
}
|
|
4438
4464
|
async signIn(params) {
|
|
4439
|
-
const { currentAddress, publicKey } = await this.accountInfo.
|
|
4465
|
+
const { address: currentAddress, publicKey } = await this.accountInfo.getCurrent();
|
|
4440
4466
|
const { signature = "" } = await this.signMessage(params);
|
|
4441
4467
|
return {
|
|
4442
4468
|
address: currentAddress,
|
|
@@ -4627,6 +4653,486 @@ var SolanaService = class _SolanaService extends BaseService {
|
|
|
4627
4653
|
}
|
|
4628
4654
|
}
|
|
4629
4655
|
};
|
|
4656
|
+
var BaseConfig2 = walletUtils.SupportedChainTypes[walletUtils.ChainTypes.DOGE];
|
|
4657
|
+
var DECIMALS = 1e8;
|
|
4658
|
+
var MYDOGE_BASE_URL = "https://api.mydoge.com";
|
|
4659
|
+
var RPC_URL = "https://api.bitcore.io/api/DOGE/mainnet";
|
|
4660
|
+
var RPC_TIMEOUT = 20 * 1e3;
|
|
4661
|
+
var network = {
|
|
4662
|
+
messagePrefix: "Dogecoin Signed Message:\n",
|
|
4663
|
+
bech32: "dc",
|
|
4664
|
+
bip44: 3,
|
|
4665
|
+
bip32: {
|
|
4666
|
+
public: 49990397,
|
|
4667
|
+
private: 49988504
|
|
4668
|
+
},
|
|
4669
|
+
pubKeyHash: 30,
|
|
4670
|
+
scriptHash: 22,
|
|
4671
|
+
wif: 158
|
|
4672
|
+
};
|
|
4673
|
+
|
|
4674
|
+
// src/dogecoin/utils-doge.ts
|
|
4675
|
+
var DogecoinUtils = class {
|
|
4676
|
+
/**
|
|
4677
|
+
* Build the PSBT from the transaction
|
|
4678
|
+
* @param tx utxoTx
|
|
4679
|
+
* @param _maximumFeeRate number (optional, currently unused)
|
|
4680
|
+
* @returns base64
|
|
4681
|
+
*/
|
|
4682
|
+
static buildPsbtToBase64(tx, _maximumFeeRate) {
|
|
4683
|
+
const psbt = new bitcoinjsLib.Psbt({ network });
|
|
4684
|
+
for (const input of tx.inputs) {
|
|
4685
|
+
const inputOptions = {
|
|
4686
|
+
hash: input.txId,
|
|
4687
|
+
index: input.vOut
|
|
4688
|
+
};
|
|
4689
|
+
if (input.nonWitnessUtxo) {
|
|
4690
|
+
inputOptions.nonWitnessUtxo = Buffer.from(input.nonWitnessUtxo, "hex");
|
|
4691
|
+
}
|
|
4692
|
+
psbt.addInput(inputOptions);
|
|
4693
|
+
}
|
|
4694
|
+
for (const output of tx.outputs) {
|
|
4695
|
+
psbt.addOutput({
|
|
4696
|
+
value: output.amount,
|
|
4697
|
+
address: output.address
|
|
4698
|
+
});
|
|
4699
|
+
}
|
|
4700
|
+
const psbtHex = psbt.toHex();
|
|
4701
|
+
return toBase64(fromHex3(psbtHex));
|
|
4702
|
+
}
|
|
4703
|
+
/**
|
|
4704
|
+
* Extract the transaction from the signed PSBT
|
|
4705
|
+
* @param signedPsbt base64
|
|
4706
|
+
* @param _maximumFeeRate number (optional, currently unused)
|
|
4707
|
+
* @returns transaction hex
|
|
4708
|
+
*/
|
|
4709
|
+
static extractPsbtTransaction(signedPsbt, _maximumFeeRate) {
|
|
4710
|
+
const signedPsbtHex = toHex3(fromBase64(signedPsbt));
|
|
4711
|
+
const psbt = bitcoinjsLib.Psbt.fromHex(signedPsbtHex, {
|
|
4712
|
+
network
|
|
4713
|
+
});
|
|
4714
|
+
const maximumFeeRate = _maximumFeeRate || 1e5;
|
|
4715
|
+
psbt.setMaximumFeeRate(maximumFeeRate);
|
|
4716
|
+
psbt.finalizeAllInputs();
|
|
4717
|
+
const transaction = psbt.extractTransaction();
|
|
4718
|
+
return transaction.toHex();
|
|
4719
|
+
}
|
|
4720
|
+
/**
|
|
4721
|
+
* Convert raw transaction hex to PSBT base64
|
|
4722
|
+
* This method converts an unsigned raw transaction to PSBT format.
|
|
4723
|
+
* Note: The rawTx should be an unsigned transaction, and the nonWitnessUtxo
|
|
4724
|
+
* for each input will need to be fetched separately from the blockchain.
|
|
4725
|
+
* @param rawTx hex string of the raw transaction
|
|
4726
|
+
* @returns base64 string of the PSBT
|
|
4727
|
+
*/
|
|
4728
|
+
static async rawTxToPsbtBase64(rawTx) {
|
|
4729
|
+
try {
|
|
4730
|
+
const cleanHex = rawTx.startsWith("0x") ? rawTx.slice(2) : rawTx;
|
|
4731
|
+
const transaction = bitcoinjsLib.Transaction.fromHex(cleanHex);
|
|
4732
|
+
const psbt = new bitcoinjsLib.Psbt({ network });
|
|
4733
|
+
for (let i = 0; i < transaction.ins.length; i++) {
|
|
4734
|
+
const input = transaction.ins[i];
|
|
4735
|
+
const hash = Buffer.from(input.hash).reverse().toString("hex");
|
|
4736
|
+
const index = input.index;
|
|
4737
|
+
const inputOptions = {
|
|
4738
|
+
hash,
|
|
4739
|
+
index,
|
|
4740
|
+
nonWitnessUtxo: input.script
|
|
4741
|
+
};
|
|
4742
|
+
psbt.addInput(inputOptions);
|
|
4743
|
+
}
|
|
4744
|
+
for (const output of transaction.outs) {
|
|
4745
|
+
try {
|
|
4746
|
+
const address = bitcoinjsLib.address.fromOutputScript(output.script, network);
|
|
4747
|
+
psbt.addOutput({
|
|
4748
|
+
address,
|
|
4749
|
+
value: Number(output.value)
|
|
4750
|
+
});
|
|
4751
|
+
} catch (error) {
|
|
4752
|
+
psbt.addOutput({
|
|
4753
|
+
script: output.script,
|
|
4754
|
+
value: Number(output.value)
|
|
4755
|
+
});
|
|
4756
|
+
}
|
|
4757
|
+
}
|
|
4758
|
+
const psbtHex = psbt.toHex();
|
|
4759
|
+
return toBase64(fromHex3(psbtHex));
|
|
4760
|
+
} catch (error) {
|
|
4761
|
+
console.warn("rawTxToPsbtBase64 failed:", error);
|
|
4762
|
+
throw new Error(
|
|
4763
|
+
`Failed to convert raw transaction to PSBT: ${error instanceof Error ? error.message : String(error)}`
|
|
4764
|
+
);
|
|
4765
|
+
}
|
|
4766
|
+
}
|
|
4767
|
+
};
|
|
4768
|
+
var KOINU_PER_DOGE = new Bignumber.BigNumber(DECIMALS);
|
|
4769
|
+
function toSatoshi(bitcion) {
|
|
4770
|
+
try {
|
|
4771
|
+
const amount = new Bignumber.BigNumber(bitcion);
|
|
4772
|
+
if (amount.isNaN() || amount.isNegative()) {
|
|
4773
|
+
throw new Error("Invalid amount");
|
|
4774
|
+
}
|
|
4775
|
+
return amount.times(KOINU_PER_DOGE).integerValue(Bignumber.BigNumber.ROUND_DOWN).toNumber();
|
|
4776
|
+
} catch (error) {
|
|
4777
|
+
throw new Error(`toSatoshi failed: ${error.message}`);
|
|
4778
|
+
}
|
|
4779
|
+
}
|
|
4780
|
+
function toBitcoin(satoshis) {
|
|
4781
|
+
try {
|
|
4782
|
+
const amount = new Bignumber.BigNumber(satoshis);
|
|
4783
|
+
if (amount.isNaN() || amount.isNegative()) {
|
|
4784
|
+
throw new Error("Invalid Koinu amount");
|
|
4785
|
+
}
|
|
4786
|
+
return amount.dividedBy(KOINU_PER_DOGE).toNumber();
|
|
4787
|
+
} catch (error) {
|
|
4788
|
+
throw new Error(`toBitcoin failed: ${error.message}`);
|
|
4789
|
+
}
|
|
4790
|
+
}
|
|
4791
|
+
function addUsedUtxos(newUsedUtxos) {
|
|
4792
|
+
const usedUtxos = walletUtils.cache.get("UsedUtxos") || {};
|
|
4793
|
+
for (const txid in newUsedUtxos) {
|
|
4794
|
+
usedUtxos[txid] = 1;
|
|
4795
|
+
}
|
|
4796
|
+
walletUtils.cache.set("UsedUtxos", usedUtxos, false);
|
|
4797
|
+
}
|
|
4798
|
+
async function createPsbt({
|
|
4799
|
+
from,
|
|
4800
|
+
to,
|
|
4801
|
+
amount,
|
|
4802
|
+
fee,
|
|
4803
|
+
spendableUtxos
|
|
4804
|
+
}) {
|
|
4805
|
+
const utxos = spendableUtxos;
|
|
4806
|
+
if (!utxos || utxos.length === 0) {
|
|
4807
|
+
throw new Error("no spendable utxos");
|
|
4808
|
+
}
|
|
4809
|
+
const sendAmount = toSatoshi(amount);
|
|
4810
|
+
const sendCost = toSatoshi(fee);
|
|
4811
|
+
const totalNeeded = sendAmount + sendCost;
|
|
4812
|
+
const sortedUtxos = utxos.sort((a, b) => b.outputValue - a.outputValue);
|
|
4813
|
+
const selectedUtxos = [];
|
|
4814
|
+
let accumulatedAmount = 0;
|
|
4815
|
+
for (const utxo of sortedUtxos) {
|
|
4816
|
+
if (accumulatedAmount >= totalNeeded) break;
|
|
4817
|
+
selectedUtxos.push(utxo);
|
|
4818
|
+
accumulatedAmount += Number(utxo.outputValue);
|
|
4819
|
+
}
|
|
4820
|
+
if (accumulatedAmount < totalNeeded) {
|
|
4821
|
+
throw new Error("not enough funds to cover amount and fee");
|
|
4822
|
+
}
|
|
4823
|
+
const utxoDetailPromises = selectedUtxos.map(async (utxo) => {
|
|
4824
|
+
try {
|
|
4825
|
+
const utxoDetail = await getTxDetail(utxo.txid);
|
|
4826
|
+
return { utxo, utxoDetail };
|
|
4827
|
+
} catch (error) {
|
|
4828
|
+
return { utxo, utxoDetail: null };
|
|
4829
|
+
}
|
|
4830
|
+
});
|
|
4831
|
+
const utxoResults = await Promise.all(utxoDetailPromises);
|
|
4832
|
+
const inputs = [];
|
|
4833
|
+
const usingUtxos = {};
|
|
4834
|
+
let addedAmount = 0;
|
|
4835
|
+
for (const { utxo, utxoDetail } of utxoResults) {
|
|
4836
|
+
if (addedAmount >= totalNeeded) break;
|
|
4837
|
+
const { txid, vout, outputValue, address = from } = utxo;
|
|
4838
|
+
if (utxoDetail?.hex && !usingUtxos[txid]) {
|
|
4839
|
+
inputs.push({
|
|
4840
|
+
txId: txid,
|
|
4841
|
+
vOut: vout,
|
|
4842
|
+
amount: Number(outputValue),
|
|
4843
|
+
nonWitnessUtxo: utxoDetail.hex,
|
|
4844
|
+
address
|
|
4845
|
+
});
|
|
4846
|
+
usingUtxos[txid] = 1;
|
|
4847
|
+
addedAmount += Number(outputValue);
|
|
4848
|
+
}
|
|
4849
|
+
}
|
|
4850
|
+
if (addedAmount < totalNeeded) {
|
|
4851
|
+
throw new Error("not enough funds to cover amount and fee");
|
|
4852
|
+
}
|
|
4853
|
+
const outputs = [
|
|
4854
|
+
{
|
|
4855
|
+
address: to,
|
|
4856
|
+
amount: sendAmount
|
|
4857
|
+
}
|
|
4858
|
+
];
|
|
4859
|
+
const changeAmount = addedAmount - sendAmount - sendCost;
|
|
4860
|
+
if (changeAmount > 0) {
|
|
4861
|
+
outputs.push({
|
|
4862
|
+
address: from,
|
|
4863
|
+
amount: changeAmount
|
|
4864
|
+
});
|
|
4865
|
+
}
|
|
4866
|
+
const params = {
|
|
4867
|
+
address: from,
|
|
4868
|
+
inputs,
|
|
4869
|
+
outputs
|
|
4870
|
+
};
|
|
4871
|
+
const psbtBase64 = DogecoinUtils.buildPsbtToBase64(params);
|
|
4872
|
+
return { psbtBase64, usingUtxos };
|
|
4873
|
+
}
|
|
4874
|
+
var mydoge = axios__default.default.create({
|
|
4875
|
+
baseURL: MYDOGE_BASE_URL
|
|
4876
|
+
});
|
|
4877
|
+
var api = axios__default.default.create({
|
|
4878
|
+
baseURL: RPC_URL,
|
|
4879
|
+
timeout: RPC_TIMEOUT
|
|
4880
|
+
});
|
|
4881
|
+
async function getBalance(address) {
|
|
4882
|
+
if (!address) {
|
|
4883
|
+
return {
|
|
4884
|
+
address: "",
|
|
4885
|
+
balance: 0
|
|
4886
|
+
};
|
|
4887
|
+
}
|
|
4888
|
+
const path = `/address/${address}?page=1&pageSize=10`;
|
|
4889
|
+
const api2 = `${MYDOGE_BASE_URL}/wallet/info?route=` + encodeURIComponent(path);
|
|
4890
|
+
const res = await mydoge.get(api2);
|
|
4891
|
+
return res.data || {};
|
|
4892
|
+
}
|
|
4893
|
+
async function getTxDetail(txId) {
|
|
4894
|
+
if (!txId) {
|
|
4895
|
+
return {};
|
|
4896
|
+
}
|
|
4897
|
+
const path = `/tx/${txId}`;
|
|
4898
|
+
const api2 = `${MYDOGE_BASE_URL}/wallet/info?route=` + encodeURIComponent(path);
|
|
4899
|
+
const res = await mydoge.get(api2);
|
|
4900
|
+
return res.data || {};
|
|
4901
|
+
}
|
|
4902
|
+
var Drc20DetailsCacheKey = "Drc20Details";
|
|
4903
|
+
walletUtils.cache.get(Drc20DetailsCacheKey) || {};
|
|
4904
|
+
async function getUtxos(address, cursor, result, filter, tx = null) {
|
|
4905
|
+
const query = (await mydoge.get(`${MYDOGE_BASE_URL}/utxos/${address}?filter=${filter}${cursor ? `&cursor=${cursor}` : ""}`)).data;
|
|
4906
|
+
let { utxos } = query;
|
|
4907
|
+
if (tx) {
|
|
4908
|
+
utxos = utxos.filter((utxo) => utxo.txid === tx?.txid && utxo.vout === tx?.vout);
|
|
4909
|
+
}
|
|
4910
|
+
result.push(
|
|
4911
|
+
...utxos.map((i) => ({
|
|
4912
|
+
txid: i.txid,
|
|
4913
|
+
vout: i.vout,
|
|
4914
|
+
outputValue: i.satoshis,
|
|
4915
|
+
script: i.script_pubkey,
|
|
4916
|
+
...filter === "inscriptions"
|
|
4917
|
+
}))
|
|
4918
|
+
);
|
|
4919
|
+
if (result.length && tx) {
|
|
4920
|
+
return;
|
|
4921
|
+
}
|
|
4922
|
+
result = result.sort((a, b) => toBitcoin(b.outputValue) - toBitcoin(a.outputValue));
|
|
4923
|
+
if (query.next_cursor) {
|
|
4924
|
+
return getUtxos(address, query.next_cursor, result, filter, tx);
|
|
4925
|
+
}
|
|
4926
|
+
}
|
|
4927
|
+
async function getSpendableUtxos(address) {
|
|
4928
|
+
const utxos = [];
|
|
4929
|
+
await getUtxos(address, 0, utxos, "spendable");
|
|
4930
|
+
return utxos;
|
|
4931
|
+
}
|
|
4932
|
+
var DuneDetailsCacheKey = "DuneDetails";
|
|
4933
|
+
walletUtils.cache.get(DuneDetailsCacheKey) || {};
|
|
4934
|
+
var sendDogeTx = async (rawTx) => {
|
|
4935
|
+
try {
|
|
4936
|
+
const res = await api.post("/tx/send", { rawTx });
|
|
4937
|
+
return res.data;
|
|
4938
|
+
} catch (e) {
|
|
4939
|
+
if (typeof e?.response?.data === "string") return Promise.reject(e?.response?.data);
|
|
4940
|
+
else return Promise.reject(e.message);
|
|
4941
|
+
}
|
|
4942
|
+
};
|
|
4943
|
+
|
|
4944
|
+
// src/dogecoin/service.ts
|
|
4945
|
+
var DogecoinService = class _DogecoinService extends BaseService {
|
|
4946
|
+
static instance;
|
|
4947
|
+
chainType;
|
|
4948
|
+
constructor(chainType, accountInfo, tomoAppInfo) {
|
|
4949
|
+
super(tomoAppInfo, accountInfo);
|
|
4950
|
+
this.chainType = chainType;
|
|
4951
|
+
}
|
|
4952
|
+
//singleton
|
|
4953
|
+
static getInstance(chainType, accountInfo, tomoAppInfo) {
|
|
4954
|
+
if (!_DogecoinService.instance) {
|
|
4955
|
+
_DogecoinService.instance = new _DogecoinService(chainType, accountInfo, tomoAppInfo);
|
|
4956
|
+
}
|
|
4957
|
+
return _DogecoinService.instance;
|
|
4958
|
+
}
|
|
4959
|
+
async requestAccounts() {
|
|
4960
|
+
const addresses = await this.accountInfo.getCurrent();
|
|
4961
|
+
const { publicKey, address } = addresses?.[0] || {};
|
|
4962
|
+
if (!address) {
|
|
4963
|
+
throw new Error("address is not set");
|
|
4964
|
+
}
|
|
4965
|
+
const { balance = 0 } = await getBalance(address);
|
|
4966
|
+
return {
|
|
4967
|
+
address,
|
|
4968
|
+
balance,
|
|
4969
|
+
approved: true,
|
|
4970
|
+
publicKey
|
|
4971
|
+
};
|
|
4972
|
+
}
|
|
4973
|
+
async getAccounts() {
|
|
4974
|
+
const accounts = await this.accountInfo.getCurrent();
|
|
4975
|
+
return accounts.map((account) => account.address);
|
|
4976
|
+
}
|
|
4977
|
+
async getConnectionStatus() {
|
|
4978
|
+
const addresses = await this.accountInfo.getCurrent();
|
|
4979
|
+
const { address } = addresses?.[0] || {};
|
|
4980
|
+
if (!address) {
|
|
4981
|
+
throw new Error("address is not set");
|
|
4982
|
+
}
|
|
4983
|
+
return {
|
|
4984
|
+
connected: true,
|
|
4985
|
+
address,
|
|
4986
|
+
selectedWalletAddress: address
|
|
4987
|
+
};
|
|
4988
|
+
}
|
|
4989
|
+
async getBalance() {
|
|
4990
|
+
const addresses = await this.accountInfo.getCurrent();
|
|
4991
|
+
const { address } = addresses?.[0] || {};
|
|
4992
|
+
if (!address) {
|
|
4993
|
+
throw new Error("address is not set");
|
|
4994
|
+
}
|
|
4995
|
+
const { balance = 0 } = await getBalance(address);
|
|
4996
|
+
return {
|
|
4997
|
+
address,
|
|
4998
|
+
balance
|
|
4999
|
+
};
|
|
5000
|
+
}
|
|
5001
|
+
async signMessage({ message, type }) {
|
|
5002
|
+
if (type) {
|
|
5003
|
+
throw new Error("bip322simple not support.");
|
|
5004
|
+
}
|
|
5005
|
+
const signature = await this.accountInfo.signMessage(message);
|
|
5006
|
+
return {
|
|
5007
|
+
signedMessage: signature
|
|
5008
|
+
};
|
|
5009
|
+
}
|
|
5010
|
+
async requestSignedMessage({
|
|
5011
|
+
message,
|
|
5012
|
+
type
|
|
5013
|
+
}) {
|
|
5014
|
+
return await this.signMessage({
|
|
5015
|
+
message,
|
|
5016
|
+
type
|
|
5017
|
+
});
|
|
5018
|
+
}
|
|
5019
|
+
async requestDecryptedMessage({ message }) {
|
|
5020
|
+
try {
|
|
5021
|
+
if (!this.accountInfo?.decryptedMessage) {
|
|
5022
|
+
throw new Error("decryptedMessage is not supported");
|
|
5023
|
+
}
|
|
5024
|
+
const unsignRes = await this.accountInfo?.decryptedMessage(message);
|
|
5025
|
+
const { text = "" } = JSON.parse(unsignRes);
|
|
5026
|
+
return {
|
|
5027
|
+
decryptedMessage: text
|
|
5028
|
+
};
|
|
5029
|
+
} catch (err) {
|
|
5030
|
+
throw new Error("requestDecryptedMessage err:" + JSON.stringify(err));
|
|
5031
|
+
}
|
|
5032
|
+
}
|
|
5033
|
+
async _queryGasInfo(txData) {
|
|
5034
|
+
const { chainId, amount = 0, decimals = 8 } = txData;
|
|
5035
|
+
const gasLimitParam = {
|
|
5036
|
+
from: txData.from,
|
|
5037
|
+
to: txData.to,
|
|
5038
|
+
value: viem.toHex(viem.parseUnits(amount.toString(), decimals))
|
|
5039
|
+
};
|
|
5040
|
+
const queryGasParams = {
|
|
5041
|
+
chainIndex: Number(chainId || BaseConfig2.chainId),
|
|
5042
|
+
callData: "0x",
|
|
5043
|
+
gasLimitParam,
|
|
5044
|
+
addressList: [txData.from]
|
|
5045
|
+
};
|
|
5046
|
+
const {
|
|
5047
|
+
data: gasInfo,
|
|
5048
|
+
success,
|
|
5049
|
+
message
|
|
5050
|
+
} = await this.transactions.queryGasInfo({
|
|
5051
|
+
chainType: this.chainType,
|
|
5052
|
+
params: queryGasParams
|
|
5053
|
+
});
|
|
5054
|
+
if (!success) {
|
|
5055
|
+
console.error("queryGasInfo doge", success, txData, queryGasParams, gasInfo);
|
|
5056
|
+
const { gasFee } = BaseConfig2;
|
|
5057
|
+
return {
|
|
5058
|
+
success: true,
|
|
5059
|
+
gasFee: gasFee.toString()
|
|
5060
|
+
};
|
|
5061
|
+
}
|
|
5062
|
+
const { baseFee = 1, gasLimit = 1 } = gasInfo;
|
|
5063
|
+
const calcFee = (feeLevel) => {
|
|
5064
|
+
const gasFee = new Bignumber.BigNumber(gasInfo[feeLevel] || baseFee).times(gasLimit);
|
|
5065
|
+
return toBitcoin(gasFee.toNumber());
|
|
5066
|
+
};
|
|
5067
|
+
const fees = {
|
|
5068
|
+
low: calcFee("priorityFeeLow"),
|
|
5069
|
+
medium: calcFee("priorityFeeMedium"),
|
|
5070
|
+
high: calcFee("priorityFeeHigh")
|
|
5071
|
+
};
|
|
5072
|
+
return {
|
|
5073
|
+
success: true,
|
|
5074
|
+
fees,
|
|
5075
|
+
gasFee: fees.high
|
|
5076
|
+
};
|
|
5077
|
+
}
|
|
5078
|
+
async requestPsbt({
|
|
5079
|
+
rawTx,
|
|
5080
|
+
signOnly
|
|
5081
|
+
}) {
|
|
5082
|
+
const psbtBase64 = await DogecoinUtils.rawTxToPsbtBase64(rawTx);
|
|
5083
|
+
const signedPsbt = await this.accountInfo.signTransaction(JSON.stringify({ psbtBase64 }));
|
|
5084
|
+
if (!signedPsbt) {
|
|
5085
|
+
return null;
|
|
5086
|
+
}
|
|
5087
|
+
const signedRawTx = DogecoinUtils.extractPsbtTransaction(signedPsbt, 1e5);
|
|
5088
|
+
if (signOnly) {
|
|
5089
|
+
return {
|
|
5090
|
+
signedRawTx
|
|
5091
|
+
};
|
|
5092
|
+
}
|
|
5093
|
+
const { txid = "" } = await sendDogeTx(signedRawTx);
|
|
5094
|
+
return {
|
|
5095
|
+
txId: txid,
|
|
5096
|
+
signedRawTx
|
|
5097
|
+
};
|
|
5098
|
+
}
|
|
5099
|
+
async requestTransaction(txData) {
|
|
5100
|
+
const spendableUtxos = txData?.spendableUtxos;
|
|
5101
|
+
if (txData.amountMismatch) {
|
|
5102
|
+
throw new Error("balance_insufficient");
|
|
5103
|
+
}
|
|
5104
|
+
if (!spendableUtxos || spendableUtxos?.length === 0) {
|
|
5105
|
+
txData.spendableUtxos = await getSpendableUtxos(txData.from);
|
|
5106
|
+
}
|
|
5107
|
+
const { psbtBase64, usingUtxos } = await createPsbt(txData);
|
|
5108
|
+
const signedPsbt = await this.accountInfo.signTransaction(JSON.stringify({ psbtBase64 }));
|
|
5109
|
+
const signedTx = DogecoinUtils.extractPsbtTransaction(signedPsbt, 1e5);
|
|
5110
|
+
if (signedTx === "") {
|
|
5111
|
+
throw new Error("Error: sign transaction err.");
|
|
5112
|
+
}
|
|
5113
|
+
try {
|
|
5114
|
+
const { txid } = await sendDogeTx(signedTx);
|
|
5115
|
+
addUsedUtxos(usingUtxos);
|
|
5116
|
+
return { txId: txid };
|
|
5117
|
+
} catch (err) {
|
|
5118
|
+
throw new Error("Error: send transaction err." + JSON.stringify(err));
|
|
5119
|
+
}
|
|
5120
|
+
}
|
|
5121
|
+
async getTransactionStatus({ txId }) {
|
|
5122
|
+
const transaction = await getTxDetail(txId);
|
|
5123
|
+
if (!transaction?.txid) {
|
|
5124
|
+
return null;
|
|
5125
|
+
}
|
|
5126
|
+
return {
|
|
5127
|
+
txId: transaction.txid,
|
|
5128
|
+
confirmations: transaction.confirmations,
|
|
5129
|
+
status: transaction.confirmations > 0 ? "confirmed" : "pending",
|
|
5130
|
+
dogeAmount: transaction.vout[0]?.value,
|
|
5131
|
+
blockTime: transaction.blockTime,
|
|
5132
|
+
address: transaction.vout[0]?.addresses[0]
|
|
5133
|
+
};
|
|
5134
|
+
}
|
|
5135
|
+
};
|
|
4630
5136
|
var TomoWallet = class _TomoWallet extends BaseService {
|
|
4631
5137
|
static instance;
|
|
4632
5138
|
walletId;
|
|
@@ -4646,8 +5152,8 @@ var TomoWallet = class _TomoWallet extends BaseService {
|
|
|
4646
5152
|
}
|
|
4647
5153
|
async getChainInfo(chainType, chainId) {
|
|
4648
5154
|
this.networks.setChainType(chainType);
|
|
4649
|
-
const
|
|
4650
|
-
return
|
|
5155
|
+
const network2 = await this.networks.getNetworkByChainId(chainId);
|
|
5156
|
+
return network2;
|
|
4651
5157
|
}
|
|
4652
5158
|
//evm chains
|
|
4653
5159
|
async isChainSupported(chainType, chainId) {
|
|
@@ -4714,12 +5220,13 @@ var TomoWallet = class _TomoWallet extends BaseService {
|
|
|
4714
5220
|
// src/index.ts
|
|
4715
5221
|
var ChainTypeServices = {
|
|
4716
5222
|
[walletUtils.ChainTypes.EVM]: EvmService,
|
|
4717
|
-
[walletUtils.ChainTypes.SOL]: SolanaService
|
|
4718
|
-
|
|
5223
|
+
[walletUtils.ChainTypes.SOL]: SolanaService,
|
|
5224
|
+
[walletUtils.ChainTypes.DOGE]: DogecoinService
|
|
4719
5225
|
};
|
|
4720
5226
|
|
|
4721
5227
|
exports.AccountType = AccountType;
|
|
4722
5228
|
exports.ChainTypeServices = ChainTypeServices;
|
|
5229
|
+
exports.DogecoinService = DogecoinService;
|
|
4723
5230
|
exports.EvmService = EvmService;
|
|
4724
5231
|
exports.SolanaService = SolanaService;
|
|
4725
5232
|
exports.TomoWallet = TomoWallet;
|