Skip to content

Commit

Permalink
Merge pull request #1979 from hirosystems/develop
Browse files Browse the repository at this point in the history
Cut beta release
  • Loading branch information
zone117x authored May 14, 2024
2 parents e8ff517 + 521d771 commit cfb2ab0
Show file tree
Hide file tree
Showing 24 changed files with 141 additions and 53 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -921,7 +921,7 @@ jobs:
type=ref,event=pr
type=semver,pattern={{version}},value=${{ steps.semantic.outputs.new_release_version }},enable=${{ steps.semantic.outputs.new_release_version != '' }}
type=semver,pattern={{major}}.{{minor}},value=${{ steps.semantic.outputs.new_release_version }},enable=${{ steps.semantic.outputs.new_release_version != '' }}
type=raw,value=latest,enable={{is_default_branch}}
type=raw,value=latest,enable=${{ github.ref == format('refs/heads/{0}', 'master') }}
- name: Login to DockerHub
uses: docker/login-action@v3
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

[![CI](https://github.com/hirosystems/stacks-blockchain-api/actions/workflows/ci.yml/badge.svg)](https://github.com/hirosystems/stacks-blockchain-api/actions/workflows/ci.yml)
[![GitHub Releases](https://img.shields.io/github/v/release/hirosystems/stacks-blockchain-api?display_name=release)](https://github.com/hirosystems/stacks-blockchain-api/releases/latest)
[![Docker Pulls](https://img.shields.io/docker/pulls/blockstack/stacks-blockchain-api-standalone)](https://hub.docker.com/r/hirosystems/stacks-blockchain-api-standalone/)
[![Docker Pulls](https://img.shields.io/docker/pulls/blockstack/stacks-blockchain-api)](https://hub.docker.com/r/hirosystems/stacks-blockchain-api/)
[![NPM client package](https://img.shields.io/badge/npm-%40stacks%2Fblockchain--api--client-blue)](https://www.npmjs.org/package/@stacks/blockchain-api-client)

## Quick start
Expand Down
10 changes: 4 additions & 6 deletions client/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,14 +45,12 @@ await sub.unsubscribe();
### Socket.io

```js
import { io } from "socket.io-client";
import * as stacks from '@stacks/blockchain-api-client';
import { StacksApiSocketClient } from '@stacks/blockchain-api-client';

// for testnet, replace with https://api.testnet.hiro.so/
const socketUrl = "https://api.mainnet.hiro.so/";
// for testnet, replace with https://api.testnet.hiro.so
const socketUrl = "https://api.mainnet.hiro.so";

const socket = io(socketUrl);
const sc = new stacks.StacksApiSocketClient(socket);
const sc = new StacksApiSocketClient({ url: socketUrl });

sc.subscribeAddressTransactions('ST3GQB6WGCWKDNFNPSQRV8DY93JN06XPZ2ZE9EVMA', (address, tx) => {
console.log('address:', address);
Expand Down
3 changes: 3 additions & 0 deletions client/src/socket-io/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ function createStacksApiSocket(opts?: StacksApiSocketConnectionOptions) {
subscriptions: Array.from(new Set(opts?.subscriptions)).join(','),
},
};
if (!socketOpts.transports) {
socketOpts.transports = ['websocket'];
}
const socket: StacksApiSocket = io(getWsUrl(opts?.url ?? BASE_PATH).href, socketOpts);
return socket;
}
Expand Down
2 changes: 1 addition & 1 deletion docker/docker-compose.dev.stacks-blockchain.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
version: '3.7'
services:
stacks-blockchain:
image: 'hirosystems/stacks-api-e2e:stacks3.0-4d11d85'
image: 'hirosystems/stacks-api-e2e:stacks3.0-0a2c0e2'
restart: on-failure
environment:
STACKS_EVENT_OBSERVER: host.docker.internal:3700
Expand Down
2 changes: 1 addition & 1 deletion docker/docker-compose.dev.stacks-krypton.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
version: '3.7'
services:
stacks-blockchain:
image: 'hirosystems/stacks-api-e2e:stacks3.0-4d11d85'
image: 'hirosystems/stacks-api-e2e:stacks3.0-0a2c0e2'
ports:
- '18443:18443' # bitcoin regtest JSON-RPC interface
- '18444:18444' # bitcoin regtest p2p
Expand Down
7 changes: 6 additions & 1 deletion docs/api/rosetta/rosetta-network-status-response.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
"current_block_identifier",
"current_block_timestamp",
"genesis_block_identifier",
"peers"
"peers",
"current_burn_block_height"
],
"properties": {
"current_block_identifier": {
Expand All @@ -31,6 +32,10 @@
"items": {
"$ref": "./../../entities/rosetta/rosetta-network-peers.schema.json"
}
},
"current_burn_block_height": {
"type": "integer",
"description": "The latest burn block height"
}
},
"additionalProperties": false
Expand Down
3 changes: 3 additions & 0 deletions docs/api/stacking/get-pox-cycle-signers.example.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,23 @@
"results": [
{
"signing_key": "0x038e3c4529395611be9abf6fa3b6987e81d402385e3d605a073f42f407565a4a3d",
"signer_address": "STRYYQQ9M8KAF4NS7WNZQYY59X93XEKR31JP64CP",
"stacked_amount": "686251350000000000",
"stacked_amount_percent": 50,
"weight": 5,
"weight_percent": 55.55555555555556
},
{
"signing_key": "0x029874497a7952483aa23890e9d0898696f33864d3df90939930a1f45421fe3b09",
"signer_address": "STF9B75ADQAVXQHNEQ6KGHXTG7JP305J2GRWF3A2",
"stacked_amount": "457500900000000000",
"stacked_amount_percent": 33.333333333333336,
"weight": 3,
"weight_percent": 33.33333333333333
},
{
"signing_key": "0x02dcde79b38787b72d8e5e0af81cffa802f0a3c8452d6b46e08859165f49a72736",
"signer_address": "ST18MDW2PDTBSCR1ACXYRJP2JX70FWNM6YY2VX4SS",
"stacked_amount": "228750450000000000",
"stacked_amount_percent": 16.666666666666668,
"weight": 1,
Expand Down
12 changes: 4 additions & 8 deletions docs/entities/rosetta/rosetta-block.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"type": "object",
"title": "RosettaBlock",
"description": "Blocks contain an array of Transactions that occurred at a particular BlockIdentifier. A hard requirement for blocks returned by Rosetta implementations is that they MUST be inalterable: once a client has requested and received a block identified by a specific BlockIndentifier, all future calls for that same BlockIdentifier must return the same block contents.",
"required": ["block_identifier", "parent_block_identifier", "timestamp", "transactions"],
"required": ["block_identifier", "parent_block_identifier", "timestamp", "transactions", "metadata"],
"additionalProperties": false,
"properties": {
"block_identifier": {
Expand All @@ -25,14 +25,10 @@
"metadata": {
"type": "object",
"description": "meta data",
"required": ["transactions_root", "difficulty"],
"required": ["burn_block_height"],
"properties": {
"transactions_root": {
"type": "string",
"description": ""
},
"difficulty": {
"type": "string",
"burn_block_height": {
"type": "number",
"description": ""
}
}
Expand Down
1 change: 1 addition & 0 deletions docs/entities/stacking/signer.example.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"signing_key": "0x038e3c4529395611be9abf6fa3b6987e81d402385e3d605a073f42f407565a4a3d",
"signer_address": "STRYYQQ9M8KAF4NS7WNZQYY59X93XEKR31JP64CP",
"stacked_amount": "686251350000000000",
"stacked_amount_percent": 50,
"weight": 5,
Expand Down
5 changes: 5 additions & 0 deletions docs/entities/stacking/signer.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"additionalProperties": false,
"required": [
"signing_key",
"signer_address",
"weight",
"stacked_amount",
"weight_percent",
Expand All @@ -13,6 +14,10 @@
"signing_key": {
"type": "string"
},
"signer_address": {
"type": "string",
"description": "The Stacks address derived from the signing_key."
},
"weight": {
"type": "integer"
},
Expand Down
16 changes: 13 additions & 3 deletions docs/generated.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -440,6 +440,9 @@ export type AbstractTransaction = BaseTransaction & {
* An ISO 8601 (YYYY-MM-DDTHH:mm:ss.sssZ) indicating when this block was mined.
*/
block_time_iso: string;
/**
* Height of the anchor burn block.
*/
burn_block_height: number;
/**
* Unix timestamp (in seconds) indicating when this block was mined
Expand Down Expand Up @@ -2361,9 +2364,8 @@ export interface RosettaBlock {
/**
* meta data
*/
metadata?: {
transactions_root: string;
difficulty: string;
metadata: {
burn_block_height: number;
[k: string]: unknown | undefined;
};
}
Expand Down Expand Up @@ -3029,6 +3031,10 @@ export interface RosettaNetworkStatusResponse {
* Peers information
*/
peers: RosettaPeers[];
/**
* The latest burn block height
*/
current_burn_block_height: number;
}
/**
* The block_identifier uniquely identifies a block in a particular network.
Expand Down Expand Up @@ -3387,6 +3393,10 @@ export interface PoxCycleSignersListResponse {
}
export interface PoxSigner {
signing_key: string;
/**
* The Stacks address derived from the signing_key.
*/
signer_address: string;
weight: number;
stacked_amount: string;
weight_percent: number;
Expand Down
3 changes: 3 additions & 0 deletions src/api/controllers/db-controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -518,6 +518,9 @@ export async function getRosettaBlockFromDataStore(
parent_block_identifier,
timestamp: dbBlock.burn_block_time * 1000,
transactions: blockTxs.found ? blockTxs.result : [],
metadata: {
burn_block_height: dbBlock.burn_block_height,
},
};
return { found: true, result: apiBlock };
});
Expand Down
2 changes: 1 addition & 1 deletion src/api/init.ts
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ export async function startApiServer(opts: {
v2.use('/smart-contracts', createV2SmartContractsRouter(datastore));
v2.use('/mempool', createMempoolRouter(datastore));
v2.use('/addresses', createV2AddressesRouter(datastore));
v2.use('/pox', createPoxRouter(datastore));
v2.use('/pox', createPoxRouter(datastore, chainId));
return v2;
})()
);
Expand Down
1 change: 1 addition & 0 deletions src/api/routes/rosetta/network.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ export function createRosettaNetworkRouter(db: PgStore, chainId: ChainID): expre
hash: genesis.block_identifier.hash,
},
peers,
current_burn_block_height: block.metadata?.burn_block_height ?? 0,
};
const nodeInfo = await stacksCoreRpcClient.getInfo();
const referenceNodeTipHeight = nodeInfo.stacks_tip_height;
Expand Down
15 changes: 14 additions & 1 deletion src/api/routes/v2/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import {
parseDbTx,
} from '../../../api/controllers/db-controller';
import { decodeClarityValueToRepr } from 'stacks-encoding-native-js';
import { TransactionVersion, getAddressFromPublicKey } from '@stacks/transactions';

export function parseDbNakamotoBlock(block: DbBlock): NakamotoBlock {
const apiBlock: NakamotoBlock = {
Expand Down Expand Up @@ -175,9 +176,14 @@ export function parseDbPoxCycle(cycle: DbPoxCycle): PoxCycle {
return result;
}

export function parseDbPoxSigner(signer: DbPoxCycleSigner): PoxSigner {
export function parseDbPoxSigner(signer: DbPoxCycleSigner, isMainnet: boolean): PoxSigner {
const signerAddress = getAddressFromPublicKey(
Buffer.from(signer.signing_key.slice(2), 'hex'),
isMainnet ? TransactionVersion.Mainnet : TransactionVersion.Testnet
);
const result: PoxSigner = {
signing_key: signer.signing_key,
signer_address: signerAddress,
weight: signer.weight,
stacked_amount: signer.stacked_amount,
weight_percent: signer.weight_percent,
Expand All @@ -192,5 +198,12 @@ export function parseDbPoxSignerStacker(stacker: DbPoxCycleSignerStacker): PoxSt
stacked_amount: stacker.locked,
pox_address: stacker.pox_addr,
};
// Special handling for pool operator stackers
if (
stacker.name === 'stack-aggregation-commit-indexed' ||
stacker.name === 'stack-aggregation-commit'
) {
result.stacked_amount = stacker.amount_ustx;
}
return result;
}
12 changes: 8 additions & 4 deletions src/api/routes/v2/pox.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,16 @@ import {
PoxCycleListResponse,
PoxCycleSignerStackersListResponse,
PoxCycleSignersListResponse,
} from 'docs/generated';
PoxSigner,
} from '@stacks/stacks-blockchain-api-types';
import { parseDbPoxCycle, parseDbPoxSigner, parseDbPoxSignerStacker } from './helpers';
import { InvalidRequestError } from '../../../errors';
import { ChainID, getChainIDNetwork } from '../../../helpers';

export function createPoxRouter(db: PgStore): express.Router {
export function createPoxRouter(db: PgStore, chainId: ChainID): express.Router {
const router = express.Router();
const cacheHandler = getETagCacheHandler(db);
const isMainnet = getChainIDNetwork(chainId) === 'mainnet';

router.get(
'/cycles',
Expand Down Expand Up @@ -83,7 +86,7 @@ export function createPoxRouter(db: PgStore): express.Router {
limit,
offset,
total,
results: results.map(r => parseDbPoxSigner(r)),
results: results.map(r => parseDbPoxSigner(r, isMainnet)),
};
setETagCacheHeaders(res);
res.json(response);
Expand All @@ -110,8 +113,9 @@ export function createPoxRouter(db: PgStore): express.Router {
res.status(404).json({ error: `Not found` });
return;
}
const response: PoxSigner = parseDbPoxSigner(signer, isMainnet);
setETagCacheHeaders(res);
res.json(parseDbPoxSigner(signer));
res.json(response);
} catch (error) {
if (error instanceof InvalidRequestError) {
res.status(404).json({ errors: error.message });
Expand Down
2 changes: 2 additions & 0 deletions src/datastore/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1094,6 +1094,8 @@ export interface DbPoxCycleSignerStacker {
stacker: string;
locked: string;
pox_addr: string;
name: string;
amount_ustx: string;
}

interface ReOrgEntities {
Expand Down
2 changes: 1 addition & 1 deletion src/datastore/pg-store-v2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -688,7 +688,7 @@ export class PgStoreV2 extends BasePgStoreModule {
);
const results = await sql<(DbPoxCycleSignerStacker & { total: number })[]>`
WITH stackers AS (
SELECT DISTINCT ON (stacker) stacker, locked, pox_addr
SELECT DISTINCT ON (stacker) stacker, locked, pox_addr, amount_ustx, name
FROM pox4_events
WHERE canonical = true
AND microblock_canonical = true
Expand Down
12 changes: 8 additions & 4 deletions src/datastore/pg-store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1938,8 +1938,10 @@ export class PgStore extends BasePgStore {
if (!dbTx.found) {
return { found: false };
}
const cols =
poxTable === 'pox4_events' ? POX4_SYNTHETIC_EVENT_COLUMNS : POX_SYNTHETIC_EVENT_COLUMNS;
const queryResults = await sql<PoxSyntheticEventQueryResult[]>`
SELECT ${sql(POX_SYNTHETIC_EVENT_COLUMNS)}
SELECT ${sql(cols)}
FROM ${sql(poxTable)}
WHERE canonical = true AND microblock_canonical = true AND tx_id = ${txId}
ORDER BY block_height DESC, microblock_sequence DESC, tx_index DESC, event_index DESC
Expand All @@ -1957,8 +1959,10 @@ export class PgStore extends BasePgStore {
poxTable: PoxSyntheticEventTable;
}): Promise<FoundOrNot<DbPoxSyntheticEvent[]>> {
return await this.sqlTransaction(async sql => {
const cols =
poxTable === 'pox4_events' ? POX4_SYNTHETIC_EVENT_COLUMNS : POX_SYNTHETIC_EVENT_COLUMNS;
const queryResults = await sql<PoxSyntheticEventQueryResult[]>`
SELECT ${sql(POX_SYNTHETIC_EVENT_COLUMNS)}
SELECT ${sql(cols)}
FROM ${sql(poxTable)}
WHERE canonical = true AND microblock_canonical = true AND stacker = ${principal}
ORDER BY block_height DESC, microblock_sequence DESC, tx_index DESC, event_index DESC
Expand Down Expand Up @@ -2349,7 +2353,7 @@ export class PgStore extends BasePgStore {
// Special case for `handle-unlock` which should be returned if it is the last received event.

const pox4EventQuery = await sql<PoxSyntheticEventQueryResult[]>`
SELECT ${sql(POX_SYNTHETIC_EVENT_COLUMNS)}
SELECT ${sql(POX4_SYNTHETIC_EVENT_COLUMNS)}
FROM pox4_events
WHERE canonical = true AND microblock_canonical = true AND stacker = ${stxAddress}
AND block_height <= ${blockHeight}
Expand Down Expand Up @@ -4243,7 +4247,7 @@ export class PgStore extends BasePgStore {

let poxV4Unlocks: StxLockEventResult[] = [];
const pox4EventQuery = await sql<PoxSyntheticEventQueryResult[]>`
SELECT DISTINCT ON (stacker) stacker, ${sql(POX_SYNTHETIC_EVENT_COLUMNS)}
SELECT DISTINCT ON (stacker) stacker, ${sql(POX4_SYNTHETIC_EVENT_COLUMNS)}
FROM pox4_events
WHERE canonical = true AND microblock_canonical = true
AND block_height <= ${block.block_height}
Expand Down
20 changes: 20 additions & 0 deletions src/tests-2.5/pox-4-delegate-aggregation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,26 @@ describe('PoX-4 - Delegate aggregation increase operations', () => {
name: 'stack-aggregation-commit-indexed',
pox_addr: delegateeAccount.btcTestnetAddr,
stacker: delegatorAccount.stxAddr,
data: expect.objectContaining({
signer_key: `0x${signerPubKey}`,
end_cycle_id: expect.stringMatching(/\d+/),
start_cycle_id: expect.stringMatching(/\d+/),
}),
})
);

const stackerRes: any = await fetchGet(`/extended/v1/pox4/stacker/${delegatorAccount.stxAddr}`);
expect(stackerRes).toBeDefined();
expect(stackerRes.results[0]).toEqual(
expect.objectContaining({
name: 'stack-aggregation-commit-indexed',
pox_addr: delegateeAccount.btcTestnetAddr,
stacker: delegatorAccount.stxAddr,
data: expect.objectContaining({
signer_key: `0x${signerPubKey}`,
end_cycle_id: expect.stringMatching(/\d+/),
start_cycle_id: expect.stringMatching(/\d+/),
}),
})
);
});
Expand Down
Loading

0 comments on commit cfb2ab0

Please sign in to comment.