From 455a3f32d99166a34cc79956abe9a76ae6d4b85c Mon Sep 17 00:00:00 2001 From: Prashant Rahul Date: Thu, 29 Jan 2026 21:37:20 +0530 Subject: [PATCH 1/2] chore: update proto for txn signing Signed-off-by: Prashant Rahul --- submodules/common | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/submodules/common b/submodules/common index da0d6e9f..249f45b9 160000 --- a/submodules/common +++ b/submodules/common @@ -1 +1 @@ -Subproject commit da0d6e9f716291bcc71d0e8fe6a5845ed677e1d3 +Subproject commit 249f45b9feccbe8f552dffdd813dba6284719fa1 From 6f403f62d1837fcc0169d7eeeed497cfcb9abbd2 Mon Sep 17 00:00:00 2001 From: Prashant Rahul Date: Fri, 30 Jan 2026 21:44:17 +0530 Subject: [PATCH 2/2] feat(cardano): add txn signing flow Signed-off-by: Prashant Rahul --- packages/app-cardano/src/app.ts | 4 + packages/app-cardano/src/operations/index.ts | 1 + .../src/operations/signTxn/index.ts | 89 +++++++++++++++++++ .../src/operations/signTxn/types.ts | 25 ++++++ packages/app-cardano/src/operations/types.ts | 1 + 5 files changed, 120 insertions(+) create mode 100644 packages/app-cardano/src/operations/signTxn/index.ts create mode 100644 packages/app-cardano/src/operations/signTxn/types.ts diff --git a/packages/app-cardano/src/app.ts b/packages/app-cardano/src/app.ts index a85e1184..3b1e3f86 100644 --- a/packages/app-cardano/src/app.ts +++ b/packages/app-cardano/src/app.ts @@ -31,6 +31,10 @@ export class CardanoApp { ); } + public async signTxn(params: operations.ISignTxnParams) { + return this.sdk.runOperation(() => operations.signTxn(this.sdk, params)); + } + public async destroy() { return this.sdk.destroy(); } diff --git a/packages/app-cardano/src/operations/index.ts b/packages/app-cardano/src/operations/index.ts index ac301862..f6018ac5 100644 --- a/packages/app-cardano/src/operations/index.ts +++ b/packages/app-cardano/src/operations/index.ts @@ -1,3 +1,4 @@ export * from './getPublicKeys'; export * from './getUserVerifiedPublicKey'; export * from './runGetPublicKeys'; +export * from './signTxn'; diff --git a/packages/app-cardano/src/operations/signTxn/index.ts b/packages/app-cardano/src/operations/signTxn/index.ts new file mode 100644 index 00000000..169773cc --- /dev/null +++ b/packages/app-cardano/src/operations/signTxn/index.ts @@ -0,0 +1,89 @@ +import { ISDK } from '@cypherock/sdk-core'; +import { + createStatusListener, + assert, + hexToUint8Array, + uint8ArrayToHex, + createLoggerWithPrefix, +} from '@cypherock/sdk-utils'; +import { APP_VERSION } from '../../constants/appId'; +import { + SeedGenerationStatus, + SignTxnStatus, +} from '../../proto/generated/types'; +import { + assertOrThrowInvalidResult, + OperationHelper, + logger as rootLogger, +} from '../../utils'; +import { ISignTxnParams, ISignTxnResult, SignTxnEvent } from './types'; + +export * from './types'; + +const logger = createLoggerWithPrefix(rootLogger, 'SignTxn'); + +export const signTxn = async ( + sdk: ISDK, + params: ISignTxnParams, +): Promise => { + assert(params, 'Params should be defined'); + assert(params.walletId, 'walletId should be defined'); + assert(params.txn, 'txn should be defined'); + assert(typeof params.txn === 'object', 'txn should be an object'); + assert( + typeof params.txn.txnDataHex === 'string', + 'txn.raw_data_hex should be a string', + ); + assert(params.derivationPath, 'derivationPath should be defined'); + assert( + params.derivationPath.length > 2, + 'derivationPath should be greater than 2', + ); + + await sdk.checkAppCompatibility(APP_VERSION); + + const { onStatus, forceStatusUpdate } = createStatusListener({ + enums: SignTxnEvent, + operationEnums: SignTxnStatus, + seedGenerationEnums: SeedGenerationStatus, + onEvent: params.onEvent, + logger, + }); + + const helper = new OperationHelper({ + sdk, + queryKey: 'signTxn', + resultKey: 'signTxn', + onStatus, + }); + + const txnBytes = hexToUint8Array(params.txn.txnDataHex); + + await helper.sendQuery({ + initiate: { + walletId: params.walletId, + derivationPath: params.derivationPath, + transactionSize: txnBytes.length, + }, + }); + + const { confirmation } = await helper.waitForResult(); + assertOrThrowInvalidResult(confirmation); + forceStatusUpdate(SignTxnEvent.CONFIRM); + + await helper.sendInChunks(txnBytes, 'txnData', 'dataAccepted'); + + await helper.sendQuery({ + signature: {}, + }); + const result = await helper.waitForResult(); + assertOrThrowInvalidResult(result.signature); + + forceStatusUpdate(SignTxnEvent.PIN_CARD); + + const signature = uint8ArrayToHex(result.signature.signature); + + return { + signature, + }; +}; diff --git a/packages/app-cardano/src/operations/signTxn/types.ts b/packages/app-cardano/src/operations/signTxn/types.ts new file mode 100644 index 00000000..e5262b14 --- /dev/null +++ b/packages/app-cardano/src/operations/signTxn/types.ts @@ -0,0 +1,25 @@ +export enum SignTxnEvent { + INIT = 0, + CONFIRM = 1, + VERIFY = 2, + PASSPHRASE = 3, + PIN_CARD = 4, +} + +export type SignTxnEventHandler = (event: SignTxnEvent) => void; + +export interface IUnsignedTransaction { + txnDataHex: string; +} + +export interface ISignTxnParams { + onEvent?: SignTxnEventHandler; + + walletId: Uint8Array; + derivationPath: number[]; + txn: IUnsignedTransaction; +} + +export interface ISignTxnResult { + signature: string; +} diff --git a/packages/app-cardano/src/operations/types.ts b/packages/app-cardano/src/operations/types.ts index 170894c2..b7adcbc3 100644 --- a/packages/app-cardano/src/operations/types.ts +++ b/packages/app-cardano/src/operations/types.ts @@ -1,2 +1,3 @@ export * from './runGetPublicKeys/types'; export * from './getUserVerifiedPublicKey/types'; +export * from './signTxn/types';