From ff66bb2eab771c16fead154607a280664eb6be4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20C=C3=A1rdenas?= Date: Tue, 22 Oct 2024 10:13:27 -0600 Subject: [PATCH] feat(ts-client): add signer messages to stacks payloads (#657) Expands the TS client to include new signer messages, and adds missing `signer_bitvec` and `signer_signatures` fields to block metadata. --- .../chainhook-sdk/src/indexer/stacks/mod.rs | 8 +- components/chainhook-types-rs/src/signers.rs | 21 ++-- components/client/typescript/src/index.ts | 1 + .../typescript/src/schemas/stacks/payload.ts | 7 +- .../typescript/src/schemas/stacks/signers.ts | 104 ++++++++++++++++++ 5 files changed, 127 insertions(+), 14 deletions(-) create mode 100644 components/client/typescript/src/schemas/stacks/signers.ts diff --git a/components/chainhook-sdk/src/indexer/stacks/mod.rs b/components/chainhook-sdk/src/indexer/stacks/mod.rs index dd2dd9dbc..c935adbe4 100644 --- a/components/chainhook-sdk/src/indexer/stacks/mod.rs +++ b/components/chainhook-sdk/src/indexer/stacks/mod.rs @@ -749,9 +749,11 @@ pub fn standardize_stacks_stackerdb_chunks( block: standardize_stacks_nakamoto_block(&nakamoto_block), }) } - SignerMessage::MockSignature(_) => StacksSignerMessage::MockSignature, - SignerMessage::MockProposal(_) => StacksSignerMessage::MockProposal, - SignerMessage::MockBlock(_) => StacksSignerMessage::MockBlock, + SignerMessage::MockSignature(_) + | SignerMessage::MockProposal(_) + | SignerMessage::MockBlock(_) => { + continue; + } }; parsed_chunks.push(StacksStackerDbChunk { contract: contract_id.clone(), diff --git a/components/chainhook-types-rs/src/signers.rs b/components/chainhook-types-rs/src/signers.rs index c1fd4e873..96d1f3ea7 100644 --- a/components/chainhook-types-rs/src/signers.rs +++ b/components/chainhook-types-rs/src/signers.rs @@ -37,16 +37,17 @@ pub struct BlockAcceptedResponse { #[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] pub enum BlockValidationFailedCode { - BadBlockHash = 0, - BadTransaction = 1, - InvalidBlock = 2, - ChainstateError = 3, - UnknownParent = 4, - NonCanonicalTenure = 5, - NoSuchTenure = 6, + BadBlockHash, + BadTransaction, + InvalidBlock, + ChainstateError, + UnknownParent, + NonCanonicalTenure, + NoSuchTenure, } #[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] +#[serde(rename_all = "SCREAMING_SNAKE_CASE")] pub enum BlockRejectReasonCode { ValidationFailed(BlockValidationFailedCode), ConnectivityIssues, @@ -66,6 +67,7 @@ pub struct BlockRejectedResponse { } #[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] +#[serde(tag = "type", content = "data")] pub enum BlockResponseData { Accepted(BlockAcceptedResponse), Rejected(BlockRejectedResponse), @@ -77,13 +79,12 @@ pub struct BlockPushedData { } #[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] +#[serde(tag = "type", content = "data")] pub enum StacksSignerMessage { BlockProposal(BlockProposalData), BlockResponse(BlockResponseData), BlockPushed(BlockPushedData), - MockProposal, - MockSignature, - MockBlock, + // TODO(rafaelcr): Add mock messages } #[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] diff --git a/components/client/typescript/src/index.ts b/components/client/typescript/src/index.ts index 8cbaab0bb..da193fc8e 100644 --- a/components/client/typescript/src/index.ts +++ b/components/client/typescript/src/index.ts @@ -152,6 +152,7 @@ export * from './schemas/payload'; export * from './schemas/predicate'; export * from './schemas/stacks/if_this'; export * from './schemas/stacks/payload'; +export * from './schemas/stacks/signers'; export * from './schemas/stacks/tx_events'; export * from './schemas/stacks/tx_kind'; export * from './server'; diff --git a/components/client/typescript/src/schemas/stacks/payload.ts b/components/client/typescript/src/schemas/stacks/payload.ts index cc1653e1e..ef5969eb3 100644 --- a/components/client/typescript/src/schemas/stacks/payload.ts +++ b/components/client/typescript/src/schemas/stacks/payload.ts @@ -8,6 +8,7 @@ import { import { StacksTransactionEventSchema } from './tx_events'; import { StacksTransactionKindSchema } from './tx_kind'; import { StacksIfThisSchema } from './if_this'; +import { StacksSignerMessageEventSchema } from './signers'; export const StacksExecutionCostSchema = Type.Optional( Type.Object({ @@ -52,7 +53,7 @@ export const StacksTransactionMetadataSchema = Type.Object({ }); export type StacksTransactionMetadata = Static; -const StacksTransactionSchema = Type.Object({ +export const StacksTransactionSchema = Type.Object({ transaction_identifier: TransactionIdentifierSchema, operations: Type.Array(RosettaOperationSchema), metadata: StacksTransactionMetadataSchema, @@ -101,9 +102,13 @@ export const StacksEventSchema = Type.Object({ }); export type StacksEvent = Static; +export const StacksNonConsensusEventSchema = Type.Union([StacksSignerMessageEventSchema]); +export type StacksNonConsensusEvent = Static; + export const StacksPayloadSchema = Type.Object({ apply: Type.Array(StacksEventSchema), rollback: Type.Array(StacksEventSchema), + events: Type.Array(StacksNonConsensusEventSchema), chainhook: Type.Object({ uuid: Type.String(), predicate: StacksIfThisSchema, diff --git a/components/client/typescript/src/schemas/stacks/signers.ts b/components/client/typescript/src/schemas/stacks/signers.ts new file mode 100644 index 000000000..701486901 --- /dev/null +++ b/components/client/typescript/src/schemas/stacks/signers.ts @@ -0,0 +1,104 @@ +import { Static, Type } from '@fastify/type-provider-typebox'; +import { BlockIdentifierSchema } from '../common'; +import { StacksTransactionSchema } from './payload'; + +export const StacksNakamotoBlockHeaderSchema = Type.Object({ + version: Type.Integer(), + chain_length: Type.Integer(), + burn_spent: Type.Integer(), + consensus_hash: Type.String(), + parent_block_id: Type.String(), + tx_merkle_root: Type.String(), + state_index_root: Type.String(), + timestamp: Type.Integer(), + miner_signature: Type.String(), + signer_signature: Type.Array(Type.String()), + pox_treatment: Type.String(), +}); +export type StacksNakamotoBlockHeader = Static; + +export const StacksNakamotoBlockSchema = Type.Object({ + header: StacksNakamotoBlockHeaderSchema, + transactions: Type.Array(StacksTransactionSchema), +}); +export type StacksNakamotoBlock = Static; + +export const StacksSignerMessageBlockProposalSchema = Type.Object({ + type: Type.Literal('BlockProposal'), + data: Type.Object({ + block: StacksNakamotoBlockSchema, + burn_height: Type.Integer(), + reward_cycle: Type.Integer(), + }), +}); +export type StacksSignerMessageBlockProposal = Static< + typeof StacksSignerMessageBlockProposalSchema +>; + +export const StacksSignerMessageBlockResponseAcceptedSchema = Type.Object({ + type: Type.Literal('Accepted'), + data: Type.Object({ + signer_signature_hash: Type.String(), + sig: Type.String(), + }), +}); +export type StacksSignerMessageBlockResponseAccepted = Static< + typeof StacksSignerMessageBlockResponseAcceptedSchema +>; + +export const StacksSignerMessageBlockResponseRejectedSchema = Type.Object({ + type: Type.Literal('Rejected'), + data: Type.Object({ + reason: Type.String(), + reason_code: Type.Union([ + Type.Literal('VALIDATION_FAILED'), + Type.Literal('CONNECTIVITY_ISSUES'), + Type.Literal('REJECTED_IN_PRIOR_ROUND'), + Type.Literal('NO_SORTITION_VIEW'), + Type.Literal('SORTITION_VIEW_MISMATCH'), + Type.Literal('TESTING_DIRECTIVE'), + ]), + signer_signature_hash: Type.String(), + chain_id: Type.Integer(), + signature: Type.String(), + }), +}); +export type StacksSignerMessageBlockResponseRejected = Static< + typeof StacksSignerMessageBlockResponseRejectedSchema +>; + +export const StacksSignerMessageBlockResponseSchema = Type.Object({ + type: Type.Literal('BlockResponse'), + data: Type.Union([ + StacksSignerMessageBlockResponseAcceptedSchema, + StacksSignerMessageBlockResponseRejectedSchema, + ]), +}); +export type StacksSignerMessageBlockResponse = Static< + typeof StacksSignerMessageBlockResponseSchema +>; + +export const StacksSignerMessageBlockPushedSchema = Type.Object({ + type: Type.Literal('BlockPushed'), + data: Type.Object({ + block: StacksNakamotoBlockSchema, + }), +}); +export type StacksSignerMessageBlockPushed = Static; + +export const StacksSignerMessageSchema = Type.Union([ + StacksSignerMessageBlockProposalSchema, + StacksSignerMessageBlockResponseSchema, + StacksSignerMessageBlockPushedSchema, +]); +export type StacksSignerMessage = Static; + +export const StacksSignerMessageEventSchema = Type.Object({ + contract: Type.String(), + sig: Type.String(), + pubkey: Type.String(), + message: StacksSignerMessageSchema, + received_at: Type.Integer(), + received_at_block: BlockIdentifierSchema, +}); +export type StacksSignerMessageEvent = Static;