Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion docker/config/btc.conf.example
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,6 @@ UTXO_SAVE_INTERVAL = 120000 # Save UTXOs interval in milliseconds
[OP_NET]
MODE = "ARCHIVE" # ARCHIVE, FULL, SNAP, LIGHT. Only ARCHIVE is supported at this time

ENABLED_AT_BLOCK = 0 # Block height at which the OP_NET should be enabled
REINDEX = false # Set to true to reindex the OP_NET
REINDEX_FROM_BLOCK = 0 # Block height from which to reindex the OP_NET

Expand Down
8 changes: 4 additions & 4 deletions src/components/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ info:
title: OpNet RPC API
description: This document is the official API documentation of OpNet JSON-RPC.
version: 1.0.0
pointerResolutionBasePath: "/"
pointerResolutionBasePath: '/'
swagger: 2.0
basePath: "/"
basePath: '/'
tags:
- name: "Websocket"
description: "OpNet websocket configuration related endpoints."
- name: 'Websocket'
description: 'OpNet websocket configuration related endpoints.'
components:
securitySchemes:
BearerAuth:
Expand Down
6 changes: 3 additions & 3 deletions src/components/schemas/_index.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ components:
address:
type: string
description: An address or public key hash.
example: "0222513da2b72f9f8e26a016087ee191fc60be4671cae286bd2f16261c026dcb12"
example: '0222513da2b72f9f8e26a016087ee191fc60be4671cae286bd2f16261c026dcb12'
required: true
InteractionTransaction:
allOf:
Expand Down Expand Up @@ -181,7 +181,7 @@ components:
data:
type: string
description: The transaction to broadcast.
example: "02000000000101"
example: '02000000000101'
required: true
psbt:
type: boolean
Expand All @@ -200,6 +200,6 @@ components:
amount:
type: number
description: The amount to wrap in satoshis
example: "0"
example: '0'
default: 1000
required: true
1 change: 0 additions & 1 deletion src/config/btc.sample.conf
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ MODE = "ARCHIVE" # ARCHIVE, FULL, LIGHT. Only ARCHIVE is supported at this time
# LIGHT NODES HAVE A LIMITED VIEW OF THE BLOCKCHAIN, they ONLY index 10k blocks from the latest block
LIGHT_MODE_FROM_BLOCK = 10000 # Number of blocks to index in light mode

ENABLED_AT_BLOCK = 0 # Block height at which the OP_NET should be enabled
REINDEX = true # Set to true to reindex the OP_NET
REINDEX_FROM_BLOCK = 800000 # Block height from which to reindex the OP_NET

Expand Down
24 changes: 16 additions & 8 deletions src/protocols/OPNetAPIProtocol.proto
Original file line number Diff line number Diff line change
Expand Up @@ -701,12 +701,12 @@ message PendingTransactionResponse {
string firstSeen = 2;
// Block height at which the transaction was observed (0x-prefixed hex).
string blockHeight = 3;
// Theoretical gas limit for OPNet execution (0x-prefixed hex).
string theoreticalGasLimit = 4;
// Priority fee attached to the transaction (0x-prefixed hex).
string priorityFee = 5;
// Whether this transaction targets an OPNet contract.
bool isOPNet = 6;
// Theoretical gas limit for OPNet execution (0x-prefixed hex). Present only for OPNet transactions.
optional string theoreticalGasLimit = 4;
// Priority fee attached to the transaction (0x-prefixed hex). Present only for OPNet transactions.
optional string priorityFee = 5;
// The OPNet transaction type (Generic, Interaction, Deployment).
string transactionType = 6;
// Whether the transaction was submitted as a PSBT.
bool psbt = 7;
// The transaction inputs.
Expand All @@ -715,6 +715,14 @@ message PendingTransactionResponse {
repeated MempoolTransactionOutput outputs = 9;
// The full raw transaction as a hex string.
string raw = 10;
// The sender address (p2tr format). Present only for OPNet transactions.
optional string from = 11;
// The target contract address (p2op format). Present only for OPNet transactions.
optional string contractAddress = 12;
// Hex-encoded calldata. Present only for OPNet transactions.
optional string calldata = 13;
// Hex-encoded bytecode. Present only for deployment transactions.
optional string bytecode = 14;
}

// Request: fetch the latest pending transactions with optional address filter.
Expand Down Expand Up @@ -755,8 +763,8 @@ message NewMempoolTransactionNotification {
uint32 subscriptionId = 1;
// The txid of the new mempool transaction.
string txId = 2;
// Whether this transaction targets an OPNet contract.
bool isOPNet = 3;
// The OPNet transaction type (Generic, Interaction, Deployment).
string transactionType = 3;
// Unix timestamp in milliseconds when the transaction was observed.
uint64 timestamp = 4;
}
29 changes: 23 additions & 6 deletions src/src/api/data-converter/TransactionConverterForAPI.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { DataConverter } from '@btc-vision/bsi-common';
import { toBase64, toHex } from '@btc-vision/bitcoin';
import { toHex } from '@btc-vision/bitcoin';
import { Binary } from 'mongodb';
import { OPNetTransactionTypes } from '../../blockchain-indexer/processor/transaction/enums/OPNetTransactionTypes.js';
import {
Expand Down Expand Up @@ -40,18 +40,35 @@ export class TransactionConverterForAPI {
) satisfies EventReceiptDataForAPI[])
: [];

const hash: string =
transaction.hash instanceof Uint8Array
? toHex(transaction.hash)
: (transaction.hash as Binary).toString('hex');

const id: string =
transaction.id instanceof Uint8Array
? toHex(transaction.id)
: (transaction.id as Binary).toString('hex');

const newTx: TransactionDocumentForAPI<OPNetTransactionTypes> = {
...transaction,
hash: toHex(transaction.hash),
id: toHex(transaction.id),
hash: hash,
id: id,
blockNumber:
'0x' + DataConverter.fromDecimal128(transaction.blockHeight || 0n).toString(16),
inputs: transaction.inputs?.map((input) => {
let originalTransactionId: string | undefined;

if (input.originalTransactionId) {
originalTransactionId =
input.originalTransactionId instanceof Uint8Array
? toHex(input.originalTransactionId)
: (input.originalTransactionId as Binary).toString('hex');
}

return {
...input,
originalTransactionId: input.originalTransactionId
? toHex(input.originalTransactionId)
: undefined,
originalTransactionId: originalTransactionId,
scriptSignature: input.scriptSignature,
};
}),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { JSONRpcMethods } from '../../../enums/JSONRpcMethods.js';
import { JSONRpcParams } from '../../JSONRpcParams.js';

export interface BlockByChecksumAsObject
extends JSONRpcParams<JSONRpcMethods.GET_BLOCK_BY_CHECKSUM> {
export interface BlockByChecksumAsObject extends JSONRpcParams<JSONRpcMethods.GET_BLOCK_BY_CHECKSUM> {
readonly blockHash: string;
readonly sendTransactions?: boolean;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { JSONRpcMethods } from '../../../enums/JSONRpcMethods.js';
import { JSONRpcParams } from '../../JSONRpcParams.js';

export interface EpochByNumberParamsAsObject
extends JSONRpcParams<JSONRpcMethods.GET_EPOCH_BY_NUMBER> {
export interface EpochByNumberParamsAsObject extends JSONRpcParams<JSONRpcMethods.GET_EPOCH_BY_NUMBER> {
readonly height: bigint | -1 | string;
readonly includeSubmissions?: boolean;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { JSONRpcMethods } from '../../../enums/JSONRpcMethods.js';
import { JSONRpcParams } from '../../JSONRpcParams.js';

export interface EpochTemplateParamsAsObject
extends JSONRpcParams<JSONRpcMethods.GET_EPOCH_TEMPLATE> {}
export interface EpochTemplateParamsAsObject extends JSONRpcParams<JSONRpcMethods.GET_EPOCH_TEMPLATE> {}

export type EpochTemplateAsArray = [EpochTemplateParamsAsObject];

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@ import { JSONRpcMethods } from '../../../enums/JSONRpcMethods.js';
import { JSONRpcParams } from '../../JSONRpcParams.js';

/** Object-form parameters for {@link JSONRpcMethods.GET_LATEST_PENDING_TRANSACTIONS}. */
export interface GetLatestPendingTransactionsParamsAsObject
extends JSONRpcParams<JSONRpcMethods.GET_LATEST_PENDING_TRANSACTIONS> {
export interface GetLatestPendingTransactionsParamsAsObject extends JSONRpcParams<JSONRpcMethods.GET_LATEST_PENDING_TRANSACTIONS> {
/** A single address to auto-resolve into all derived wallet address types. */
readonly address?: string;
/** Explicit list of addresses to filter mempool transactions by. */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@ import { JSONRpcMethods } from '../../../enums/JSONRpcMethods.js';
import { JSONRpcParams } from '../../JSONRpcParams.js';

/** Object-form parameters for {@link JSONRpcMethods.GET_MEMPOOL_INFO} (none required). */
export interface GetMempoolInfoParamsAsObject
extends JSONRpcParams<JSONRpcMethods.GET_MEMPOOL_INFO> {}
export interface GetMempoolInfoParamsAsObject extends JSONRpcParams<JSONRpcMethods.GET_MEMPOOL_INFO> {}

/** Array-form parameters (empty). */
export type GetMempoolInfoParamsAsArray = [];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@ import { JSONRpcMethods } from '../../../enums/JSONRpcMethods.js';
import { JSONRpcParams } from '../../JSONRpcParams.js';

/** Object-form parameters for {@link JSONRpcMethods.GET_PENDING_TRANSACTION}. */
export interface GetPendingTransactionParamsAsObject
extends JSONRpcParams<JSONRpcMethods.GET_PENDING_TRANSACTION> {
export interface GetPendingTransactionParamsAsObject extends JSONRpcParams<JSONRpcMethods.GET_PENDING_TRANSACTION> {
/** The 64-character hex transaction hash. */
readonly hash: string;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { JSONRpcMethods } from '../../../enums/JSONRpcMethods.js';
import { JSONRpcParams } from '../../JSONRpcParams.js';

export interface BroadcastTransactionParamsAsObject
extends JSONRpcParams<JSONRpcMethods.GET_TRANSACTION_BY_HASH> {
export interface BroadcastTransactionParamsAsObject extends JSONRpcParams<JSONRpcMethods.GET_TRANSACTION_BY_HASH> {
readonly data: string;
readonly psbt?: boolean;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { JSONRpcMethods } from '../../../enums/JSONRpcMethods.js';
import { JSONRpcParams } from '../../JSONRpcParams.js';

export interface TransactionByHashParamsAsObject
extends JSONRpcParams<JSONRpcMethods.GET_TRANSACTION_BY_HASH> {
export interface TransactionByHashParamsAsObject extends JSONRpcParams<JSONRpcMethods.GET_TRANSACTION_BY_HASH> {
readonly hash: string;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { JSONRpcMethods } from '../../../enums/JSONRpcMethods.js';
import { JSONRpcParams } from '../../JSONRpcParams.js';

export interface TransactionReceiptsParamsAsObject
extends JSONRpcParams<JSONRpcMethods.GET_TRANSACTION_RECEIPT> {
export interface TransactionReceiptsParamsAsObject extends JSONRpcParams<JSONRpcMethods.GET_TRANSACTION_RECEIPT> {
readonly hash: string;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,8 @@ export interface MempoolTransactionData {
readonly firstSeen: string;
/** Block height at which the transaction was observed (`0x`-prefixed hex). */
readonly blockHeight: string;
/** Theoretical gas limit for OPNet execution (`0x`-prefixed hex). */
readonly theoreticalGasLimit: string;
/** Priority fee attached to the transaction (`0x`-prefixed hex). */
readonly priorityFee: string;
/** Whether this transaction targets an OPNet contract. */
readonly isOPNet: boolean;
/** The OPNet transaction type (Generic, Interaction, Deployment). */
readonly transactionType: string;
/** Whether the transaction was submitted as a PSBT. */
readonly psbt: boolean;
/** The transaction inputs. */
Expand All @@ -40,4 +36,19 @@ export interface MempoolTransactionData {
readonly outputs: MempoolTransactionOutput[];
/** The full raw transaction as a hex string. */
readonly raw: string;

// OPNet-specific fields (present only for OPNet transactions)

/** Theoretical gas limit for OPNet execution (`0x`-prefixed hex). */
readonly theoreticalGasLimit?: string;
/** Priority fee attached to the transaction (`0x`-prefixed hex). */
readonly priorityFee?: string;
/** The sender address (p2tr format). */
readonly from?: string;
/** The target contract address (p2op format). */
readonly contractAddress?: string;
/** Hex-encoded calldata. */
readonly calldata?: string;
/** Hex-encoded bytecode (deployment transactions only). */
readonly bytecode?: string;
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ interface IBroadcastTransactionResult {
identifier?: bigint;
modifiedTransaction?: string;
finalizedTransaction?: boolean;
transactionType?: string;
}

export type BroadcastTransactionResult = IBroadcastTransactionResult;
4 changes: 3 additions & 1 deletion src/src/api/routes/api/v1/address/GetBalanceRoute.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,9 @@ export class GetBalanceRoute extends Route<
if (data) {
this.safeJson(res, 200, data);
} else {
this.safeJson(res, 400, { error: 'Could not fetch balance for the given address.' });
this.safeJson(res, 400, {
error: 'Could not fetch balance for the given address.',
});
}
} catch (err) {
this.handleDefaultError(res, err as Error);
Expand Down
18 changes: 15 additions & 3 deletions src/src/api/routes/api/v1/block/BlockByChecksum.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,12 @@ export class BlockByChecksum extends BlockRoute<Routes.BLOCK_BY_CHECKSUM> {
let blockChecksum: SafeString =
BlockParamsConverter.getParameterAsStringForBlock(params);

blockChecksum = blockChecksum ? (blockChecksum.startsWith('0x') ? blockChecksum.slice(2) : blockChecksum).toLowerCase() : null;
blockChecksum = blockChecksum
? (blockChecksum.startsWith('0x')
? blockChecksum.slice(2)
: blockChecksum
).toLowerCase()
: null;

const includeTransactions: boolean = this.getParameterAsBoolean(params);
if (!blockChecksum) {
Expand All @@ -34,7 +39,12 @@ export class BlockByChecksum extends BlockRoute<Routes.BLOCK_BY_CHECKSUM> {

if (blockChecksum.length !== 64) throw new Error(`Invalid checksum length`);

return await this.getCachedBlockData(includeTransactions, undefined, blockChecksum, true);
return await this.getCachedBlockData(
includeTransactions,
undefined,
blockChecksum,
true,
);
} catch (e) {
if (Config.DEV_MODE) {
this.error(`Error details: ${(e as Error).stack}`);
Expand Down Expand Up @@ -86,7 +96,9 @@ export class BlockByChecksum extends BlockRoute<Routes.BLOCK_BY_CHECKSUM> {
if (data) {
this.safeJson(res, 200, data);
} else {
this.safeJson(res, 400, { error: 'Could not fetch latest block header. Is this node synced?' });
this.safeJson(res, 400, {
error: 'Could not fetch latest block header. Is this node synced?',
});
}
} catch (err) {
this.handleDefaultError(res, err as Error);
Expand Down
4 changes: 3 additions & 1 deletion src/src/api/routes/api/v1/block/BlockByHash.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,9 @@ export class BlockByHash extends BlockRoute<Routes.BLOCK_BY_HASH> {
if (data) {
this.safeJson(res, 200, data);
} else {
this.safeJson(res, 400, { error: 'Could not fetch latest block header. Is this node synced?' });
this.safeJson(res, 400, {
error: 'Could not fetch latest block header. Is this node synced?',
});
}
} catch (err) {
this.handleDefaultError(res, err as Error);
Expand Down
4 changes: 3 additions & 1 deletion src/src/api/routes/api/v1/block/BlockByNumber.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,9 @@ export class BlockByNumber extends BlockRoute<Routes.BLOCK_BY_ID> {
if (data) {
this.safeJson(res, 200, data);
} else {
this.safeJson(res, 400, { error: 'Could not fetch latest block header. Is this node synced?' });
this.safeJson(res, 400, {
error: 'Could not fetch latest block header. Is this node synced?',
});
}
} catch (err) {
this.handleDefaultError(res, err as Error);
Expand Down
4 changes: 3 additions & 1 deletion src/src/api/routes/api/v1/block/GasRoute.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,9 @@ export class GasRoute extends Route<Routes.GAS, JSONRpcMethods.GAS, BlockGasInfo
if (data) {
this.safeJson(res, 200, data);
} else {
this.safeJson(res, 400, { error: 'Could not fetch latest block header. Is this node synced?' });
this.safeJson(res, 400, {
error: 'Could not fetch latest block header. Is this node synced?',
});
}
} catch (err) {
this.handleDefaultError(res, err as Error);
Expand Down
4 changes: 3 additions & 1 deletion src/src/api/routes/api/v1/block/LatestBlock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,9 @@ export class LatestBlock extends Route<
if (data) {
this.safeJson(res, 200, data);
} else {
this.safeJson(res, 400, { error: 'Could not fetch latest block header. Is this node synced?' });
this.safeJson(res, 400, {
error: 'Could not fetch latest block header. Is this node synced?',
});
}
} catch (err) {
this.handleDefaultError(res, err as Error);
Expand Down
4 changes: 3 additions & 1 deletion src/src/api/routes/api/v1/chain/ReorgRoute.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,9 @@ export class ReorgRoute extends Route<Routes.REORG, JSONRpcMethods.REORG, ReorgR
if (data) {
this.safeJson(res, 200, data);
} else {
this.safeJson(res, 400, { error: 'Could not fetch latest block header. Is this node synced?' });
this.safeJson(res, 400, {
error: 'Could not fetch latest block header. Is this node synced?',
});
}
} catch (err) {
this.handleDefaultError(res, err as Error);
Expand Down
Loading