Skip to content

Commit

Permalink
feat: dogecoin
Browse files Browse the repository at this point in the history
  • Loading branch information
kvhnuke committed Sep 14, 2023
1 parent d96bd26 commit c94fcf8
Show file tree
Hide file tree
Showing 17 changed files with 169 additions and 76 deletions.
16 changes: 7 additions & 9 deletions packages/extension/src/providers/bitcoin/libs/api-ss.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
import { BTCRawInfo } from "@/types/activity";
import { ProviderAPIInterface } from "@/types/provider";
import { hexToBuffer } from "@enkryptcom/utils";
import {
BitcoinNetworkInfo,
HaskoinUnspentType,
SSTxType,
SSUnspentType,
} from "../types";
import { payments } from "bitcoinjs-lib";
import { toBN } from "web3-utils";
import cacheFetch from "@/libs/cache-fetch";
import { getAddress as getBitcoinAddress } from "../types/bitcoin-network";

class API implements ProviderAPIInterface {
node: string;
Expand All @@ -24,11 +23,7 @@ class API implements ProviderAPIInterface {
return this;
}
private getAddress(pubkey: string) {
const { address } = payments.p2wpkh({
pubkey: hexToBuffer(pubkey),
network: this.networkInfo,
});
return address as string;
return getBitcoinAddress(pubkey, this.networkInfo);
}
// eslint-disable-next-line @typescript-eslint/no-empty-function
async init(): Promise<void> {}
Expand Down Expand Up @@ -63,9 +58,11 @@ class API implements ProviderAPIInterface {
const address = pubkey.length < 64 ? pubkey : this.getAddress(pubkey);
return fetch(`${this.node}/api/v1/account/${address}`)
.then((res) => res.json())
.then((balance: { balance: string }) => {
.then((balance: { balance: string; unconfirmedBalance: string }) => {
if ((balance as any).message) return "0";
return toBN(balance.balance).toString();
return toBN(balance.balance)
.add(toBN(balance.unconfirmedBalance))
.toString();
});
}
async broadcastTx(rawtx: string): Promise<boolean> {
Expand Down Expand Up @@ -104,6 +101,7 @@ class API implements ProviderAPIInterface {
pkscript: res.vout[utx.vout].scriptPubKey.hex,
txid: utx.txid,
value: Number(utx.value),
raw: res.hex,
});
}
ret.sort((a, b) => {
Expand Down
9 changes: 2 additions & 7 deletions packages/extension/src/providers/bitcoin/libs/api.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
import { BTCRawInfo } from "@/types/activity";
import { ProviderAPIInterface } from "@/types/provider";
import { hexToBuffer } from "@enkryptcom/utils";
import {
BitcoinNetworkInfo,
HaskoinBalanceType,
HaskoinTxType,
HaskoinUnspentType,
} from "../types";
import { payments } from "bitcoinjs-lib";
import { toBN } from "web3-utils";
import { getAddress as getBitcoinAddress } from "../types/bitcoin-network";

class API implements ProviderAPIInterface {
node: string;
Expand All @@ -23,11 +22,7 @@ class API implements ProviderAPIInterface {
return this;
}
private getAddress(pubkey: string) {
const { address } = payments.p2wpkh({
pubkey: hexToBuffer(pubkey),
network: this.networkInfo,
});
return address as string;
return getBitcoinAddress(pubkey, this.networkInfo);
}
// eslint-disable-next-line @typescript-eslint/no-empty-function
async init(): Promise<void> {}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,11 @@ const SSFeeHandler = async (
if (json.fast.satsPerKiloByte < 0)
json.fast.satsPerKiloByte = json.average.satsPerKiloByte;
return {
[GasPriceTypes.FASTEST]: Math.ceil(json.fast.satsPerKiloByte / 1024),
[GasPriceTypes.FAST]: Math.ceil(json.fast.satsPerKiloByte / 1024),
[GasPriceTypes.REGULAR]: Math.ceil(json.average.satsPerKiloByte / 1024),
[GasPriceTypes.FASTEST]:
Math.ceil(json.fast.satsPerKiloByte / 1024) + 5,
[GasPriceTypes.FAST]: Math.ceil(json.fast.satsPerKiloByte / 1024) + 3,
[GasPriceTypes.REGULAR]:
Math.ceil(json.average.satsPerKiloByte / 1024) + 2,
[GasPriceTypes.ECONOMY]: Math.ceil(json.slow.satsPerKiloByte / 1024),
};
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { NetworkNames } from "@enkryptcom/types";
import {
BitcoinNetwork,
BitcoinNetworkOptions,
PaymentType,
} from "../types/bitcoin-network";
import { haskoinHandler } from "../libs/activity-handlers";
import wrapActivityHandler from "@/libs/activity-state/wrap-activity-handler";
Expand Down Expand Up @@ -43,6 +44,7 @@ const bitcoinOptions: BitcoinNetworkOptions = {
scriptHash: 0xc4,
wif: 0xef,
dustThreshold: null,
paymentType: PaymentType.P2WPKH,
},
};

Expand Down
2 changes: 2 additions & 0 deletions packages/extension/src/providers/bitcoin/networks/bitcoin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { NetworkNames } from "@enkryptcom/types";
import {
BitcoinNetwork,
BitcoinNetworkOptions,
PaymentType,
} from "../types/bitcoin-network";
import { haskoinHandler } from "../libs/activity-handlers";
import wrapActivityHandler from "@/libs/activity-state/wrap-activity-handler";
Expand Down Expand Up @@ -36,6 +37,7 @@ const bitcoinOptions: BitcoinNetworkOptions = {
scriptHash: 0x05,
wif: 0x80,
dustThreshold: null,
paymentType: PaymentType.P2WPKH,
},
};

Expand Down
48 changes: 48 additions & 0 deletions packages/extension/src/providers/bitcoin/networks/dogecoin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { NetworkNames } from "@enkryptcom/types";
import {
BitcoinNetwork,
BitcoinNetworkOptions,
PaymentType,
} from "../types/bitcoin-network";
import { ssHandler } from "../libs/activity-handlers";
import wrapActivityHandler from "@/libs/activity-state/wrap-activity-handler";
import SSFeeHandler from "../libs/ss-fee-handler";
import SSApi from "../libs/api-ss";

const dogeOptions: BitcoinNetworkOptions = {
name: NetworkNames.Dogecoin,
name_long: "Dogecoin",
homePage: "https://dogecoin.com/",
blockExplorerTX: "https://dogechain.info/tx/[[txHash]]",
blockExplorerAddr: "https://dogechain.info/address/[[address]]",
isTestNetwork: false,
currencyName: "Doge",
currencyNameLong: "Dogecoin",
icon: require("./icons/doge.svg"),
decimals: 8,
node: "https://partners.mewapi.io/nodes/ss/doge",
coingeckoID: "dogecoin",
apiType: SSApi,
activityHandler: wrapActivityHandler(ssHandler),
basePath: "m/44'/3'/0'/0",
feeHandler: () => {
return SSFeeHandler("https://partners.mewapi.io/nodes/ss/doge/api/v1/fees");
},
networkInfo: {
messagePrefix: "\x19Dogecoin Signed Message:\n",
bech32: "dc",
bip32: {
public: 0x02facafd,
private: 0x02fac398,
},
pubKeyHash: 0x1e,
scriptHash: 0x16,
wif: 0x9e,
dustThreshold: null,
paymentType: PaymentType.P2PKH,
},
};

const dogecoin = new BitcoinNetwork(dogeOptions);

export default dogecoin;
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions packages/extension/src/providers/bitcoin/networks/index.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import btcNode from "./bitcoin";
import btcTestNode from "./bitcoin-testnet";
import ltcNode from "./litecoin";
import dogeNode from "./dogecoin";

export default {
bitcoin: btcNode,
bitcoinTest: btcTestNode,
litecoin: ltcNode,
dogecoin: dogeNode,
};
2 changes: 2 additions & 0 deletions packages/extension/src/providers/bitcoin/networks/litecoin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { NetworkNames } from "@enkryptcom/types";
import {
BitcoinNetwork,
BitcoinNetworkOptions,
PaymentType,
} from "../types/bitcoin-network";
import { ssHandler } from "../libs/activity-handlers";
import wrapActivityHandler from "@/libs/activity-state/wrap-activity-handler";
Expand Down Expand Up @@ -38,6 +39,7 @@ const litecoinOptions: BitcoinNetworkOptions = {
scriptHash: 0x32,
wif: 0xb0,
dustThreshold: null,
paymentType: PaymentType.P2WPKH,
},
};

Expand Down
22 changes: 14 additions & 8 deletions packages/extension/src/providers/bitcoin/types/bitcoin-network.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ import { GasPriceTypes } from "@/providers/common/types";
import type HaskoinAPI from "@/providers/bitcoin/libs/api";
import type SSAPI from "@/providers/bitcoin/libs/api-ss";

export enum PaymentType {
P2PKH = "p2pkh",
P2WPKH = "p2wpkh",
}
export interface BitcoinNetworkOptions {
name: NetworkNames;
name_long: string;
Expand All @@ -45,6 +49,14 @@ export interface BitcoinNetworkOptions {
apiType: typeof HaskoinAPI | typeof SSAPI;
}

export const getAddress = (pubkey: string, network: BitcoinNetworkInfo) => {
if (pubkey.length < 64) return pubkey;
const { address } = payments[network.paymentType]({
network,
pubkey: hexToBuffer(pubkey),
});
return address as string;
};
export class BitcoinNetwork extends BaseNetwork {
public assets: BaseToken[] = [];
public networkInfo: BitcoinNetworkInfo;
Expand All @@ -64,14 +76,8 @@ export class BitcoinNetwork extends BaseNetwork {
identicon: createIcon,
signer: [SignerType.secp256k1btc],
provider: ProviderName.bitcoin,
displayAddress: (pubkey: string) => {
if (pubkey.length < 64) return pubkey;
const { address } = payments.p2wpkh({
pubkey: hexToBuffer(pubkey),
network: options.networkInfo,
});
return address as string;
},
displayAddress: (pubkey: string) =>
getAddress(pubkey, options.networkInfo),
api,
...options,
};
Expand Down
4 changes: 4 additions & 0 deletions packages/extension/src/providers/bitcoin/types/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { NetworkNames } from "@enkryptcom/types";
import type { Provider as InjectedProvider } from "../inject";
import { PaymentType } from "./bitcoin-network";

export const BitcoinNetworks = {
BTC: NetworkNames.Bitcoin,
Expand All @@ -17,6 +18,7 @@ export interface BitcoinNetworkInfo {
scriptHash: number;
wif: number;
dustThreshold: null;
paymentType: PaymentType;
}

export interface HaskoinBalanceType {
Expand All @@ -37,6 +39,7 @@ export interface HaskoinUnspentType {
index: number;
pkscript: string;
value: number;
raw?: string;
}
export interface SSUnspentType {
txid: string;
Expand Down Expand Up @@ -77,6 +80,7 @@ export interface SSTxType {
timestamp: number;
confirmations: number;
fee: string;
hex: string;
vin: {
txid: string;
addresses?: string[];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ import { GasPriceTypes } from "@/providers/common/types";
import { RPCTxType } from "../types";
import BitcoinAPI from "@/providers/bitcoin/libs/api";
import { HaskoinUnspentType } from "../types";
import { calculateSize } from "./libs/tx-size";
import { calculateSizeBasedOnType } from "./libs/tx-size";
import { getGasCostValues } from "../libs/utils";
import { computed } from "@vue/reactivity";
import { toBN } from "web3-utils";
Expand Down Expand Up @@ -233,13 +233,10 @@ const updateUTXOs = async () => {
const api = (await network.value.api()) as BitcoinAPI;
return api.getUTXOs(account.value.address).then((utxos) => {
accountUTXOs.value = utxos;
const txSize = calculateSize(
{
input_count: accountUTXOs.value.length,
},
{
p2wpkh_output_count: 2,
}
const txSize = calculateSizeBasedOnType(
accountUTXOs.value.length,
2,
(network.value as BitcoinNetwork).networkInfo.paymentType
);
setTransactionFees(Math.ceil(txSize.txVBytes));
});
Expand All @@ -254,6 +251,7 @@ const getTxInfo = () => {
txInfo.inputs.push({
hash: u.txid,
index: u.index,
raw: u.raw,
witnessUtxo: {
script: u.pkscript,
value: u.value,
Expand Down
29 changes: 21 additions & 8 deletions packages/extension/src/providers/bitcoin/ui/libs/signer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import sendUsingInternalMessengers from "@/libs/messenger/internal-messenger";
import { hexToBuffer } from "@enkryptcom/utils";
import { Psbt } from "bitcoinjs-lib";
import { signAsync } from "bitcoinjs-message";
import { PaymentType } from "../../types/bitcoin-network";

const TransactionSigner = (
options: SignerTransactionOptions
Expand Down Expand Up @@ -33,14 +34,26 @@ const TransactionSigner = (
};
const tx = new Psbt({ network: network.networkInfo });
payload.inputs
.map((u) => ({
hash: u.hash,
index: u.index,
witnessUtxo: {
script: Buffer.from(u.witnessUtxo.script, "hex"),
value: u.witnessUtxo.value,
},
}))
.map((u) => {
const res: {
hash: string;
index: number;
witnessUtxo?: { script: Buffer; value: number };
nonWitnessUtxo?: Buffer;
} = {
hash: u.hash,
index: u.index,
};
if (network.networkInfo.paymentType === PaymentType.P2WPKH) {
res.witnessUtxo = {
script: Buffer.from(u.witnessUtxo.script, "hex"),
value: u.witnessUtxo.value,
};
} else if (network.networkInfo.paymentType === PaymentType.P2PKH) {
res.nonWitnessUtxo = Buffer.from(u.raw, "hex");
}
return res;
})
.forEach((input) => tx.addInput(input));
payload.outputs.forEach((output) => tx.addOutput(output));
return tx.signAllInputsAsync(signer).then(() => {
Expand Down
Loading

1 comment on commit c94fcf8

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.