From 969feafd9a4b134acce1b63d1b45467b997ca0a7 Mon Sep 17 00:00:00 2001 From: Rafa Cardenas <253999660+rafa-stacks@users.noreply.github.com> Date: Tue, 24 Mar 2026 08:54:13 -0600 Subject: [PATCH 1/5] fix: make address be optional in signing payload schema --- packages/schemas/src/schemas/entities/construction.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/schemas/src/schemas/entities/construction.ts b/packages/schemas/src/schemas/entities/construction.ts index 845f876..77841f0 100644 --- a/packages/schemas/src/schemas/entities/construction.ts +++ b/packages/schemas/src/schemas/entities/construction.ts @@ -9,7 +9,7 @@ export const PublicKeySchema = Type.Object({ export type PublicKey = Static; export const SigningPayloadSchema = Type.Object({ - address: Type.String(), + address: Type.Optional(Type.String()), account_identifier: AccountIndentifierSchema, hex_bytes: HexStringSchema, signature_type: Type.Literal('ecdsa_recovery'), From 8c4bf3e12dd51142d34664cd1676fd0eaba25ffd Mon Sep 17 00:00:00 2001 From: Rafa Cardenas <253999660+rafa-stacks@users.noreply.github.com> Date: Tue, 24 Mar 2026 08:55:39 -0600 Subject: [PATCH 2/5] chore(release): 0.4.3 [skip ci] --- package-lock.json | 8 ++++---- package.json | 2 +- packages/api/openapi.yaml | 2 +- packages/api/package.json | 2 +- packages/schemas/package.json | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index ca64348..572afa4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "stacks-mesh-api", - "version": "0.4.2", + "version": "0.4.3", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "stacks-mesh-api", - "version": "0.4.2", + "version": "0.4.3", "license": "MIT", "workspaces": [ "packages/*" @@ -5009,7 +5009,7 @@ }, "packages/api": { "name": "@stacks/mesh-api", - "version": "0.4.2", + "version": "0.4.3", "license": "MIT", "dependencies": { "@fastify/cors": "^11.2.0", @@ -5085,7 +5085,7 @@ }, "packages/schemas": { "name": "@stacks/mesh-schemas", - "version": "0.4.2", + "version": "0.4.3", "license": "MIT", "devDependencies": { "typescript": "^5.7.3" diff --git a/package.json b/package.json index b9e1bf9..3cb0c87 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "stacks-mesh-api", - "version": "0.4.2", + "version": "0.4.3", "private": true, "description": "Mesh API implementation for Stacks blockchain - monorepo", "workspaces": [ diff --git a/packages/api/openapi.yaml b/packages/api/openapi.yaml index b3bea03..931a148 100644 --- a/packages/api/openapi.yaml +++ b/packages/api/openapi.yaml @@ -2,7 +2,7 @@ openapi: 3.0.3 info: title: Stacks Mesh API description: A Mesh API (formerly Rosetta API) implementation for the Stacks blockchain - version: 0.4.2 + version: 0.4.3 components: schemas: {} paths: diff --git a/packages/api/package.json b/packages/api/package.json index a283aba..a049ee0 100644 --- a/packages/api/package.json +++ b/packages/api/package.json @@ -1,6 +1,6 @@ { "name": "@stacks/mesh-api", - "version": "0.4.2", + "version": "0.4.3", "description": "Mesh API implementation for Stacks blockchain", "main": "dist/index.js", "type": "module", diff --git a/packages/schemas/package.json b/packages/schemas/package.json index fd02808..3ffa004 100644 --- a/packages/schemas/package.json +++ b/packages/schemas/package.json @@ -1,6 +1,6 @@ { "name": "@stacks/mesh-schemas", - "version": "0.4.2", + "version": "0.4.3", "description": "Mesh API schemas for Stacks blockchain transactions and blocks", "type": "module", "main": "dist/index.js", From b39a3ab2bf4c3263c331fdc8b5e3b024687c1ee3 Mon Sep 17 00:00:00 2001 From: Rafa Cardenas <253999660+rafa-stacks@users.noreply.github.com> Date: Tue, 24 Mar 2026 09:09:07 -0600 Subject: [PATCH 3/5] principal schema --- packages/schemas/src/schemas/entities/construction.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/schemas/src/schemas/entities/construction.ts b/packages/schemas/src/schemas/entities/construction.ts index 77841f0..56852db 100644 --- a/packages/schemas/src/schemas/entities/construction.ts +++ b/packages/schemas/src/schemas/entities/construction.ts @@ -1,5 +1,5 @@ import { Static, Type } from '@sinclair/typebox'; -import { AccountIndentifierSchema, AmountSchema } from '../index.js'; +import { AccountIndentifierSchema, AmountSchema, StacksPrincipalSchema } from '../index.js'; import { HexStringSchema, Nullable, OperationIdentifierSchema } from './common.js'; export const PublicKeySchema = Type.Object({ @@ -9,7 +9,7 @@ export const PublicKeySchema = Type.Object({ export type PublicKey = Static; export const SigningPayloadSchema = Type.Object({ - address: Type.Optional(Type.String()), + address: Type.Optional(StacksPrincipalSchema), account_identifier: AccountIndentifierSchema, hex_bytes: HexStringSchema, signature_type: Type.Literal('ecdsa_recovery'), From f4aba8c9495359ec99ba79b3a9e88700c6da943e Mon Sep 17 00:00:00 2001 From: Rafa Cardenas <253999660+rafa-stacks@users.noreply.github.com> Date: Wed, 25 Mar 2026 08:52:08 -0600 Subject: [PATCH 4/5] fix account identifier typo --- packages/schemas/src/schemas/entities/common.ts | 4 ++-- .../schemas/src/schemas/entities/construction.ts | 12 ++++++------ packages/schemas/src/schemas/entities/operations.ts | 4 ++-- packages/schemas/src/schemas/requests/account.ts | 6 +++--- .../schemas/src/schemas/responses/construction.ts | 8 ++++---- 5 files changed, 17 insertions(+), 17 deletions(-) diff --git a/packages/schemas/src/schemas/entities/common.ts b/packages/schemas/src/schemas/entities/common.ts index ef0b9fb..d38e36c 100644 --- a/packages/schemas/src/schemas/entities/common.ts +++ b/packages/schemas/src/schemas/entities/common.ts @@ -41,11 +41,11 @@ export const SubAccountIdentifierSchema = Type.Object({ }); export type SubAccountIdentifier = Static; -export const AccountIndentifierSchema = Type.Object({ +export const AccountIdentifierSchema = Type.Object({ address: StacksPrincipalSchema, sub_account: Type.Optional(SubAccountIdentifierSchema), }); -export type AccountIdentifier = Static; +export type AccountIdentifier = Static; export const BlockIdentifierSchema = Type.Object({ index: Type.Integer({ minimum: 1 }), diff --git a/packages/schemas/src/schemas/entities/construction.ts b/packages/schemas/src/schemas/entities/construction.ts index 56852db..ee6418a 100644 --- a/packages/schemas/src/schemas/entities/construction.ts +++ b/packages/schemas/src/schemas/entities/construction.ts @@ -1,5 +1,5 @@ import { Static, Type } from '@sinclair/typebox'; -import { AccountIndentifierSchema, AmountSchema, StacksPrincipalSchema } from '../index.js'; +import { AccountIdentifierSchema, AmountSchema, StacksPrincipalSchema } from '../index.js'; import { HexStringSchema, Nullable, OperationIdentifierSchema } from './common.js'; export const PublicKeySchema = Type.Object({ @@ -10,7 +10,7 @@ export type PublicKey = Static; export const SigningPayloadSchema = Type.Object({ address: Type.Optional(StacksPrincipalSchema), - account_identifier: AccountIndentifierSchema, + account_identifier: AccountIdentifierSchema, hex_bytes: HexStringSchema, signature_type: Type.Literal('ecdsa_recovery'), }); @@ -86,7 +86,7 @@ export type ConstructionMetadata = Static; export const ConstructionFeeOperationSchema = Type.Object({ operation_identifier: OperationIdentifierSchema, type: Type.Literal('fee'), - account: AccountIndentifierSchema, + account: AccountIdentifierSchema, amount: AmountSchema, }); export type ConstructionFeeOperation = Static; @@ -94,7 +94,7 @@ export type ConstructionFeeOperation = Static; export const AccountCoinsRequestSchema = Type.Object({ network_identifier: NetworkIdentifierSchema, - account_identifier: AccountIndentifierSchema, + account_identifier: AccountIdentifierSchema, include_mempool: Type.Boolean(), currencies: Type.Optional(Type.Array(CurrencySchema)), }); diff --git a/packages/schemas/src/schemas/responses/construction.ts b/packages/schemas/src/schemas/responses/construction.ts index a2b1fdf..fc6f0f1 100644 --- a/packages/schemas/src/schemas/responses/construction.ts +++ b/packages/schemas/src/schemas/responses/construction.ts @@ -1,5 +1,5 @@ import { Static, Type } from '@sinclair/typebox'; -import { AccountIndentifierSchema, HexStringSchema } from '../entities/common.js'; +import { AccountIdentifierSchema, HexStringSchema } from '../entities/common.js'; import { AmountSchema, OperationSchema } from '../entities/operations.js'; import { TransactionIdentifierSchema } from '../entities/common.js'; import { @@ -10,13 +10,13 @@ import { export const ConstructionDeriveResponseSchema = Type.Object({ address: Type.Optional(Type.String()), - account_identifier: Type.Optional(AccountIndentifierSchema), + account_identifier: Type.Optional(AccountIdentifierSchema), }); export type ConstructionDeriveResponse = Static; export const ConstructionPreprocessResponseSchema = Type.Object({ options: Type.Optional(ConstructionOptionsSchema), - required_public_keys: Type.Optional(Type.Array(AccountIndentifierSchema)), + required_public_keys: Type.Optional(Type.Array(AccountIdentifierSchema)), }); export type ConstructionPreprocessResponse = Static; @@ -40,7 +40,7 @@ export type ConstructionCombineResponse = Static; From 124807b8fbf7cf7501f7aa9aff6ffcc60f1b5ef1 Mon Sep 17 00:00:00 2001 From: Rafa Cardenas <253999660+rafa-stacks@users.noreply.github.com> Date: Wed, 25 Mar 2026 08:57:09 -0600 Subject: [PATCH 5/5] add test --- .../api/tests/construction/combine.test.ts | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/packages/api/tests/construction/combine.test.ts b/packages/api/tests/construction/combine.test.ts index ac44bbc..d988b27 100644 --- a/packages/api/tests/construction/combine.test.ts +++ b/packages/api/tests/construction/combine.test.ts @@ -76,6 +76,37 @@ describe('/construction/combine', () => { assert.ok(body.signed_transaction.length >= unsignedTx.length); }); + test('combines unsigned transaction when signing payload address is omitted', async () => { + // Sign the sighash offline + const signature = addHexPrefix(signWithKey(SENDER_PRIVATE_KEY, removeHexPrefix(sighash))); + + const res = await post(fastify, '/construction/combine', { + network_identifier: NETWORK_IDENTIFIER, + unsigned_transaction: unsignedTx, + signatures: [ + { + signing_payload: { + hex_bytes: sighash, + account_identifier: { + address: senderAddress, + }, + signature_type: 'ecdsa_recovery', + }, + public_key: { + hex_bytes: senderPublicKey, + curve_type: 'secp256k1', + }, + signature_type: 'ecdsa_recovery', + hex_bytes: signature, + }, + ], + }); + assert.equal(res.statusCode, 200); + const body = JSON.parse(res.body); + assert.ok(body.signed_transaction); + assert.ok(body.signed_transaction.length >= unsignedTx.length); + }); + test('rejects when no signatures are provided', async () => { const res = await post(fastify, '/construction/combine', { network_identifier: NETWORK_IDENTIFIER,