Skip to content

Commit

Permalink
feat: fractal support
Browse files Browse the repository at this point in the history
  • Loading branch information
veralygit committed Oct 25, 2024
1 parent 2e00b50 commit a8a235c
Show file tree
Hide file tree
Showing 15 changed files with 129 additions and 77 deletions.
17 changes: 13 additions & 4 deletions packages/sdk/src/api/jsonrpc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,19 @@ export const rpc = {
get id() {
return Math.floor(Math.random() * 100000)
},
mainnet: new JsonRpc(getRpcUrl(apiConfig.apis.mainnet.batter)),
testnet: new JsonRpc(getRpcUrl(apiConfig.apis.testnet.batter)),
signet: new JsonRpc(getRpcUrl(apiConfig.apis.signet.batter)),
regtest: new JsonRpc(getRpcUrl(apiConfig.apis.regtest.batter))
bitcoin: {
mainnet: new JsonRpc(getRpcUrl(apiConfig.apis.bitcoin.mainnet.batter)),
testnet: new JsonRpc(getRpcUrl(apiConfig.apis.bitcoin.testnet.batter)),
signet: new JsonRpc(getRpcUrl(apiConfig.apis.bitcoin.signet.batter)),
regtest: new JsonRpc(getRpcUrl(apiConfig.apis.bitcoin.regtest.batter))
},
"fractal-bitcoin": {
mainnet: new JsonRpc(getRpcUrl(apiConfig.apis["fractal-bitcoin"].mainnet.batter)),
testnet: new JsonRpc(getRpcUrl(apiConfig.apis["fractal-bitcoin"].testnet.batter)),
// unused
signet: new JsonRpc(getRpcUrl(apiConfig.apis["fractal-bitcoin"].signet.batter)),
regtest: new JsonRpc(getRpcUrl(apiConfig.apis["fractal-bitcoin"].regtest.batter))
}
} as const

/*
Expand Down
60 changes: 42 additions & 18 deletions packages/sdk/src/config/index.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,49 @@
export const apiConfig = {
version: "0.0.0.10",
apis: {
mainnet: {
batter: "https://mainnet.ordit.io/",
orderbook: "1H4vvBnr62YWQmvNSt8Z4pDw3Vcv1n5xz7",
ipfs: "http://ipfs-gateway.ordit.io/"
bitcoin: {
mainnet: {
batter: "https://mainnet.ordit.io/",
orderbook: "1H4vvBnr62YWQmvNSt8Z4pDw3Vcv1n5xz7",
ipfs: "http://ipfs-gateway.ordit.io/"
},
regtest: {
batter: "https://regtest.ordit.io/",
orderbook: "bcrt1q2ys7qws8g072dqe3psp92pqz93ac6wmztexkh5",
ipfs: "http://ipfs-gateway.ordit.io/"
},
testnet: {
batter: "https://testnet.ordit.io/",
orderbook: "tb1qfnw26753j7kqu3q099sd48htvtk5wm4e0enmru",
ipfs: "http://ipfs-gateway.ordit.io/"
},
signet: {
batter: "https://signet.ordit.io/",
orderbook: "tb1qfnw26753j7kqu3q099sd48htvtk5wm4e0enmru",
ipfs: "http://ipfs-gateway.ordit.io/"
}
},
regtest: {
batter: "https://regtest.ordit.io/",
orderbook: "bcrt1q2ys7qws8g072dqe3psp92pqz93ac6wmztexkh5",
ipfs: "http://ipfs-gateway.ordit.io/"
},
testnet: {
batter: "https://testnet.ordit.io/",
orderbook: "tb1qfnw26753j7kqu3q099sd48htvtk5wm4e0enmru",
ipfs: "http://ipfs-gateway.ordit.io/"
},
signet: {
batter: "https://signet.ordit.io/",
orderbook: "tb1qfnw26753j7kqu3q099sd48htvtk5wm4e0enmru",
ipfs: "http://ipfs-gateway.ordit.io/"
"fractal-bitcoin": {
mainnet: {
batter: "https://fractal.ordit.io/",
orderbook: "",
ipfs: "http://ipfs-gateway.ordit.io/"
},
regtest: {
batter: "https://fractal-regtest.ordit.io/",
orderbook: "",
ipfs: "http://ipfs-gateway.ordit.io/"
},
testnet: {
batter: "https://fractal-testnet.ordit.io/",
orderbook: "",
ipfs: "http://ipfs-gateway.ordit.io/"
},
signet: {
batter: "https://fractal-signet.ordit.io/",
orderbook: "",
ipfs: "http://ipfs-gateway.ordit.io/"
}
}
}
}
Expand Down
8 changes: 5 additions & 3 deletions packages/sdk/src/fee/FeeEstimator.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Psbt } from "bitcoinjs-lib"

import { AddressFormats, getNetwork, getScriptType } from ".."
import { Network } from "../config/types"
import { Chain, Network } from "../config/types"
import { MAXIMUM_FEE } from "../constants"
import { OrditSDKError } from "../utils/errors"
import { FeeEstimatorOptions } from "./types"
Expand All @@ -14,16 +14,18 @@ export default class FeeEstimator {
protected witness?: Buffer[] = []
protected virtualSize = 0
protected weight = 0
protected chain: Chain

constructor({ feeRate, network, psbt, witness }: FeeEstimatorOptions) {
constructor({ feeRate, network, psbt, witness, chain = "bitcoin" }: FeeEstimatorOptions) {
if (feeRate < 0 || !Number.isSafeInteger(feeRate)) {
throw new OrditSDKError("Invalid feeRate")
}

this.feeRate = +feeRate // convert decimal to whole number that might have passed Number.isSafeInteger check due to precision loss
this.network = network
this.witness = witness || []
this.psbt = psbt || new Psbt({ network: getNetwork(this.network) })
this.psbt = psbt || new Psbt({ network: getNetwork(chain === "fractal-bitcoin" ? "mainnet" : this.network) })
this.chain = chain
}

get data() {
Expand Down
3 changes: 2 additions & 1 deletion packages/sdk/src/fee/types.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { Psbt } from "bitcoinjs-lib"

import { Network } from "../config/types"
import { Chain, Network } from "../config/types"

export interface FeeEstimatorOptions {
feeRate: number
network: Network
psbt?: Psbt
witness?: Buffer[]
chain?: Chain
}
11 changes: 3 additions & 8 deletions packages/sdk/src/inscription/collection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,6 @@ export async function publishCollection({
throw new OrditSDKError("Invalid inscriptions supplied.")
}

network = chain === "fractal-bitcoin" ? "mainnet" : network

if (royalty) {
// 0 = 0%, 0.1 = 10%
if (isNaN(royalty.pct) || royalty.pct < 0 || royalty.pct > MAXIMUM_ROYALTY_PERCENTAGE) {
Expand Down Expand Up @@ -64,7 +62,7 @@ export async function publishCollection({
insc: inscriptions
}

return new Inscriber({ ...options, meta: collectionMeta, network })
return new Inscriber({ ...options, meta: collectionMeta, network, chain })
}

export async function mintFromCollection({ chain = "bitcoin", ...options }: MintFromCollectionOptions) {
Expand All @@ -76,9 +74,7 @@ export async function mintFromCollection({ chain = "bitcoin", ...options }: Mint
throw new OrditSDKError("Invalid chain supplied.")
}

options.network = chain === "fractal-bitcoin" ? "mainnet" : options.network

const datasource = options.datasource || new JsonRpcDatasource({ network: options.network })
const datasource = options.datasource || new JsonRpcDatasource({ network: options.network, chain })
const collection = await datasource.getInscription({ id: options.collectionInscriptionId })
if (!collection) {
throw new OrditSDKError("Invalid collection")
Expand Down Expand Up @@ -143,8 +139,6 @@ export async function bulkMintFromCollection({
throw new OrditSDKError("Invalid chain supplied.")
}

network = chain === "fractal-bitcoin" ? "mainnet" : network

let currentPointer = 0

const { metaList, inscriptionList } = inscriptions.reduce<{
Expand Down Expand Up @@ -191,6 +185,7 @@ export async function bulkMintFromCollection({

return new InscriberV2({
address,
chain,
publicKey,
feeRate,
datasource,
Expand Down
2 changes: 0 additions & 2 deletions packages/sdk/src/instant-trade/InstantTradeBuyerTxBuilder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,6 @@ export default class InstantTradeBuyerTxBuilder extends InstantTradeBuilder {
throw new OrditSDKError("Invalid chain supplied")
}

network = chain === "fractal-bitcoin" ? "mainnet" : network

super({
address,
datasource,
Expand Down
2 changes: 0 additions & 2 deletions packages/sdk/src/instant-trade/InstantTradeSellerTxBuilder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,6 @@ export default class InstantTradeSellerTxBuilder extends InstantTradeBuilder {
throw new OrditSDKError("Invalid chain supplied")
}

network = chain === "fractal-bitcoin" ? "mainnet" : network

super({
address,
datasource,
Expand Down
8 changes: 6 additions & 2 deletions packages/sdk/src/modules/BaseDatasource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,22 @@ import {
GetUnspentsResponse,
RelayOptions
} from "../api/types"
import { Network } from "../config/types"
import { Network, Chain } from "../config/types"
import { Transaction, UTXO, UTXOLimited } from "../transactions/types"

interface BaseDatasourceOptions {
network: Network
chain?: Chain
}

export default abstract class BaseDatasource {
protected readonly network: Network

constructor({ network }: BaseDatasourceOptions) {
protected readonly chain: Chain

constructor({ chain = "bitcoin", network }: BaseDatasourceOptions) {
this.network = network
this.chain = chain
}

abstract getBalance({ address }: GetBalanceOptions): Promise<number>
Expand Down
25 changes: 13 additions & 12 deletions packages/sdk/src/modules/JsonRpcDatasource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,35 +13,36 @@ import {
GetUnspentsResponse,
RelayOptions
} from "../api/types"
import { Network } from "../config/types"
import { Chain, Network } from "../config/types"
import { Transaction, UTXO, UTXOLimited } from "../transactions/types"
import { OrditSDKError } from "../utils/errors"
import { BaseDatasource, DatasourceUtility } from "."
import { JsonRpcPagination } from "./types"

interface JsonRpcDatasourceOptions {
network: Network
chain?: Chain
}

export default class JsonRpcDatasource extends BaseDatasource {
constructor({ network }: JsonRpcDatasourceOptions) {
super({ network })
constructor({ chain = "bitcoin", network }: JsonRpcDatasourceOptions) {
super({ chain, network })
}

async getBalance({ address }: GetBalanceOptions) {
if (!address) {
throw new OrditSDKError("Invalid request")
}

return rpc[this.network].call<number>("Address.GetBalance", { address }, rpc.id)
return rpc[this.chain][this.network].call<number>("Address.GetBalance", { address }, rpc.id)
}

async getInscription({ id, decodeMetadata }: GetInscriptionOptions) {
if (!id) {
throw new OrditSDKError("Invalid request")
}

let inscription = await rpc[this.network].call<Inscription>("Ordinals.GetInscription", { id }, rpc.id)
let inscription = await rpc[this.chain][this.network].call<Inscription>("Ordinals.GetInscription", { id }, rpc.id)
if (decodeMetadata) {
inscription = DatasourceUtility.transformInscriptions([inscription])[0]
}
Expand All @@ -54,7 +55,7 @@ export default class JsonRpcDatasource extends BaseDatasource {
throw new OrditSDKError("Invalid request")
}

return rpc[this.network].call<UTXO>("Ordinals.GetInscriptionUtxo", { id }, rpc.id)
return rpc[this.chain][this.network].call<UTXO>("Ordinals.GetInscriptionUtxo", { id }, rpc.id)
}

async getInscriptions({
Expand All @@ -71,7 +72,7 @@ export default class JsonRpcDatasource extends BaseDatasource {
}: GetInscriptionsOptions) {
let inscriptions: Inscription[] = []
do {
const { inscriptions: _inscriptions, pagination } = await rpc[this.network].call<{
const { inscriptions: _inscriptions, pagination } = await rpc[this.chain][this.network].call<{
inscriptions: Inscription[]
pagination: JsonRpcPagination
}>(
Expand Down Expand Up @@ -102,7 +103,7 @@ export default class JsonRpcDatasource extends BaseDatasource {
throw new OrditSDKError("Invalid request")
}

return rpc[this.network].call<UTXOLimited[]>(
return rpc[this.chain][this.network].call<UTXOLimited[]>(
"Address.GetSpendables",
{
address,
Expand All @@ -127,7 +128,7 @@ export default class JsonRpcDatasource extends BaseDatasource {
throw new OrditSDKError("Invalid request")
}

const tx = await rpc[this.network].call<Transaction>(
const tx = await rpc[this.chain][this.network].call<Transaction>(
"Transactions.GetTransaction",
{
txid: txId,
Expand Down Expand Up @@ -165,7 +166,7 @@ export default class JsonRpcDatasource extends BaseDatasource {
throw new OrditSDKError("Invalid address")
}

const response = await rpc[this.network].call<Transactions>(
const response = await rpc[this.chain][this.network].call<Transactions>(
"Address.GetTransactions",
{
address,
Expand Down Expand Up @@ -204,7 +205,7 @@ export default class JsonRpcDatasource extends BaseDatasource {

let utxos: UTXO[] = []
do {
const { unspents, pagination } = await rpc[this.network].call<{
const { unspents, pagination } = await rpc[this.chain][this.network].call<{
unspents: UTXO[]
pagination: JsonRpcPagination
}>(
Expand Down Expand Up @@ -240,6 +241,6 @@ export default class JsonRpcDatasource extends BaseDatasource {
throw new OrditSDKError("Invalid max fee rate")
}

return rpc[this.network].call<string>("Transactions.Relay", { hex, maxFeeRate, validate }, rpc.id)
return rpc[this.chain][this.network].call<string>("Transactions.Relay", { hex, maxFeeRate, validate }, rpc.id)
}
}
16 changes: 11 additions & 5 deletions packages/sdk/src/transactions/Inscriber.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
OnOffUnion,
TaptreeVersion
} from ".."
import { Network } from "../config/types"
import { Chain, Network } from "../config/types"
import { MINIMUM_AMOUNT_IN_SATS } from "../constants"
import { OrditSDKError } from "../utils/errors"
import { NestedObject } from "../utils/types"
Expand Down Expand Up @@ -65,7 +65,8 @@ export class Inscriber extends PSBTBuilder {
safeMode,
meta,
taptreeVersion,
datasource
datasource,
chain = "bitcoin"
}: InscriberArgOptions) {
super({
address,
Expand All @@ -75,7 +76,8 @@ export class Inscriber extends PSBTBuilder {
publicKey,
outputs,
autoAdjustment: false,
datasource
datasource,
chain
})
if (!publicKey || !changeAddress || !mediaContent) {
throw new OrditSDKError("Invalid options provided")
Expand Down Expand Up @@ -276,7 +278,7 @@ export class Inscriber extends PSBTBuilder {
this.buildTaprootTree()
this.payment = bitcoin.payments.p2tr({
internalPubkey: Buffer.from(this.xKey, "hex"),
network: getNetwork(this.network),
network: getNetwork(this.chain === "fractal-bitcoin" ? "mainnet" : this.network),
scriptTree: this.taprootTree,
redeem: this.getReedemScript()
})
Expand All @@ -295,7 +297,9 @@ export class Inscriber extends PSBTBuilder {
this.recovery = true
this.buildTaprootTree()

this.payment = createTransaction(Buffer.from(this.xKey, "hex"), "p2tr", this.network, {
const _network = getNetwork(this.chain === "fractal-bitcoin" ? "mainnet" : this.network)

this.payment = createTransaction(Buffer.from(this.xKey, "hex"), "p2tr", _network, {
scriptTree: this.taprootTree,
redeem: this.getRecoveryRedeemScript()
})
Expand All @@ -317,6 +321,7 @@ export class Inscriber extends PSBTBuilder {
try {
await this.fetchAndSelectSuitableUnspent({ skipStrictSatsCheck, customAmount })
} catch (error) {
console.log(error)
return false
}
}
Expand Down Expand Up @@ -367,6 +372,7 @@ export type InscriberArgOptions = Pick<GetWalletOptions, "safeMode"> & {
outputs?: Outputs
encodeMetadata?: boolean
datasource?: BaseDatasource
chain?: Chain
}

type Outputs = Array<{ address: string; value: number }>
Loading

0 comments on commit a8a235c

Please sign in to comment.