@odatano/core 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (98) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +212 -0
  3. package/cds-plugin.js +5 -0
  4. package/config/preview/cardano-node/alonzo-genesis.json +196 -0
  5. package/config/preview/cardano-node/byron-genesis.json +117 -0
  6. package/config/preview/cardano-node/config.json +118 -0
  7. package/config/preview/cardano-node/conway-genesis.json +297 -0
  8. package/config/preview/cardano-node/shelley-genesis.json +68 -0
  9. package/config/preview/cardano-node/topology.json +19 -0
  10. package/db/schema.cds +1318 -0
  11. package/package.json +125 -0
  12. package/src/index.d.ts.map +1 -0
  13. package/src/index.js +96 -0
  14. package/src/index.js.map +1 -0
  15. package/src/plugin.d.ts.map +1 -0
  16. package/src/plugin.js +92 -0
  17. package/src/plugin.js.map +1 -0
  18. package/srv/blockchain/backends/blockfrost-backend.d.ts.map +1 -0
  19. package/srv/blockchain/backends/blockfrost-backend.js +398 -0
  20. package/srv/blockchain/backends/blockfrost-backend.js.map +1 -0
  21. package/srv/blockchain/backends/cardano-backend.d.ts.map +1 -0
  22. package/srv/blockchain/backends/cardano-backend.js +12 -0
  23. package/srv/blockchain/backends/cardano-backend.js.map +1 -0
  24. package/srv/blockchain/backends/koios-backend.d.ts.map +1 -0
  25. package/srv/blockchain/backends/koios-backend.js +537 -0
  26. package/srv/blockchain/backends/koios-backend.js.map +1 -0
  27. package/srv/blockchain/backends/ogmios-backend.d.ts.map +1 -0
  28. package/srv/blockchain/backends/ogmios-backend.js +516 -0
  29. package/srv/blockchain/backends/ogmios-backend.js.map +1 -0
  30. package/srv/blockchain/cardano-client.d.ts.map +1 -0
  31. package/srv/blockchain/cardano-client.js +377 -0
  32. package/srv/blockchain/cardano-client.js.map +1 -0
  33. package/srv/blockchain/cardano-indexer.d.ts.map +1 -0
  34. package/srv/blockchain/cardano-indexer.js +542 -0
  35. package/srv/blockchain/cardano-indexer.js.map +1 -0
  36. package/srv/blockchain/cardano-tx-builder.d.ts.map +1 -0
  37. package/srv/blockchain/cardano-tx-builder.js +232 -0
  38. package/srv/blockchain/cardano-tx-builder.js.map +1 -0
  39. package/srv/blockchain/circuit-breaker.d.ts.map +1 -0
  40. package/srv/blockchain/circuit-breaker.js +110 -0
  41. package/srv/blockchain/circuit-breaker.js.map +1 -0
  42. package/srv/blockchain/signing/external-signer.d.ts.map +1 -0
  43. package/srv/blockchain/signing/external-signer.js +302 -0
  44. package/srv/blockchain/signing/external-signer.js.map +1 -0
  45. package/srv/blockchain/signing/signature-verifier.d.ts.map +1 -0
  46. package/srv/blockchain/signing/signature-verifier.js +249 -0
  47. package/srv/blockchain/signing/signature-verifier.js.map +1 -0
  48. package/srv/blockchain/transaction-building/buildooor-tx.d.ts.map +1 -0
  49. package/srv/blockchain/transaction-building/buildooor-tx.js +636 -0
  50. package/srv/blockchain/transaction-building/buildooor-tx.js.map +1 -0
  51. package/srv/blockchain/transaction-building/cardano-tx.d.ts.map +1 -0
  52. package/srv/blockchain/transaction-building/cardano-tx.js +3 -0
  53. package/srv/blockchain/transaction-building/cardano-tx.js.map +1 -0
  54. package/srv/blockchain/transaction-building/csl-tx.d.ts.map +1 -0
  55. package/srv/blockchain/transaction-building/csl-tx.js +766 -0
  56. package/srv/blockchain/transaction-building/csl-tx.js.map +1 -0
  57. package/srv/blockchain/transaction-building/tx-builder-registry.d.ts.map +1 -0
  58. package/srv/blockchain/transaction-building/tx-builder-registry.js +67 -0
  59. package/srv/blockchain/transaction-building/tx-builder-registry.js.map +1 -0
  60. package/srv/cardano-service.cds +179 -0
  61. package/srv/cardano-service.d.ts.map +1 -0
  62. package/srv/cardano-service.js +227 -0
  63. package/srv/cardano-service.js.map +1 -0
  64. package/srv/cardano-tx-service.cds +298 -0
  65. package/srv/cardano-tx-service.d.ts.map +1 -0
  66. package/srv/cardano-tx-service.js +646 -0
  67. package/srv/cardano-tx-service.js.map +1 -0
  68. package/srv/cardano-ui.cds +2949 -0
  69. package/srv/server.d.ts.map +1 -0
  70. package/srv/server.js +212 -0
  71. package/srv/server.js.map +1 -0
  72. package/srv/utils/backend-request-handler.d.ts.map +1 -0
  73. package/srv/utils/backend-request-handler.js +47 -0
  74. package/srv/utils/backend-request-handler.js.map +1 -0
  75. package/srv/utils/const.d.ts.map +1 -0
  76. package/srv/utils/const.js +86 -0
  77. package/srv/utils/const.js.map +1 -0
  78. package/srv/utils/error-codes.d.ts.map +1 -0
  79. package/srv/utils/error-codes.js +49 -0
  80. package/srv/utils/error-codes.js.map +1 -0
  81. package/srv/utils/errors.d.ts.map +1 -0
  82. package/srv/utils/errors.js +389 -0
  83. package/srv/utils/errors.js.map +1 -0
  84. package/srv/utils/mappers.d.ts.map +1 -0
  85. package/srv/utils/mappers.js +723 -0
  86. package/srv/utils/mappers.js.map +1 -0
  87. package/srv/utils/signing-helper.d.ts.map +1 -0
  88. package/srv/utils/signing-helper.js +128 -0
  89. package/srv/utils/signing-helper.js.map +1 -0
  90. package/srv/utils/tx-build-helper.d.ts.map +1 -0
  91. package/srv/utils/tx-build-helper.js +135 -0
  92. package/srv/utils/tx-build-helper.js.map +1 -0
  93. package/srv/utils/types.d.ts.map +1 -0
  94. package/srv/utils/types.js +36 -0
  95. package/srv/utils/types.js.map +1 -0
  96. package/srv/utils/validators.d.ts.map +1 -0
  97. package/srv/utils/validators.js +382 -0
  98. package/srv/utils/validators.js.map +1 -0
@@ -0,0 +1,232 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.CardanoTransactionBuilder = void 0;
7
+ const cds_1 = __importDefault(require("@sap/cds"));
8
+ const tx_builder_registry_1 = require("./transaction-building/tx-builder-registry");
9
+ const logger = cds_1.default.log('CardanoTransactionBuilder');
10
+ /**
11
+ * CardanoTransactionBuilder - High-level transaction builder that utilizes specific CardanoTxBuilder implementations
12
+ * to build various types of Cardano transactions.
13
+ */
14
+ class CardanoTransactionBuilder {
15
+ client;
16
+ txBuilder;
17
+ initialized = false;
18
+ /**
19
+ * Create a new CardanoTransactionBuilder instance
20
+ * @param client - The CardanoClient instance for UTxO fetching
21
+ */
22
+ constructor(client) {
23
+ this.client = client;
24
+ logger.info('CardanoTransactionBuilder instance created');
25
+ }
26
+ /**
27
+ * Initialize the transaction builder
28
+ * @param protocolParams - Optional protocol parameters (if not provided, fetched from backend)
29
+ */
30
+ async init(protocolParams) {
31
+ if (this.initialized && this.txBuilder)
32
+ return;
33
+ // Create transaction builder from registry
34
+ this.txBuilder = tx_builder_registry_1.TxBuilderRegistry.createDefault();
35
+ await this.txBuilder.init(this.client, protocolParams);
36
+ this.initialized = true;
37
+ logger.info(`Initialized with builder: ${this.txBuilder.name}`);
38
+ }
39
+ /**
40
+ * Ensure the builder is initialized and return it (lazy init)
41
+ * @returns {Promise<CardanoTxBuilder>} initialized builder
42
+ * @throws {Error} if builder cannot be initialized
43
+ */
44
+ async ensureInitialized() {
45
+ if (!this.initialized || !this.txBuilder) {
46
+ await this.init();
47
+ }
48
+ if (!this.txBuilder) {
49
+ throw new Error('Transaction builder failed to initialize');
50
+ }
51
+ return this.txBuilder;
52
+ }
53
+ /**
54
+ * Reset the transaction builder (useful for testing)
55
+ */
56
+ reset() {
57
+ this.txBuilder = undefined;
58
+ this.initialized = false;
59
+ logger.debug(`Builder reset`);
60
+ }
61
+ /**
62
+ * Set the transaction builder directly (for testing)
63
+ * @param builder - The builder to set
64
+ */
65
+ setBuilder(builder) {
66
+ this.txBuilder = builder;
67
+ this.initialized = true;
68
+ }
69
+ /**
70
+ * Build a simple ADA transfer transaction
71
+ * @param req transaction build request
72
+ * @param protocolParameters current protocol parameters
73
+ * @returns {Promise<TxBuildResult>} transaction build result
74
+ */
75
+ async buildSimpleAdaTransaction(req, protocolParameters) {
76
+ const builder = await this.ensureInitialized();
77
+ // Prepare the transaction build context
78
+ const txContext = {
79
+ utxos: await this._fetchUtxosForAddress(req.senderAddress),
80
+ protocolParameters: protocolParameters
81
+ };
82
+ // Build the unsigned ADA transfer transaction
83
+ const txBuildResult = await builder.buildUnsignedAdaTransfer(req, txContext);
84
+ logger.info(`Built simple ADA transaction successfully.`);
85
+ // Return the transaction build result
86
+ return txBuildResult;
87
+ }
88
+ async buildTransactionWithMetadata(req, protocolParameters) {
89
+ const builder = await this.ensureInitialized();
90
+ // Prepare the transaction build context
91
+ const txContext = {
92
+ utxos: await this._fetchUtxosForAddress(req.senderAddress),
93
+ protocolParameters: protocolParameters
94
+ };
95
+ // Build the unsigned transaction with metadata
96
+ const txBuildResult = await builder.buildUnsignedTransactionWithMetadata(req, txContext);
97
+ logger.info(`Built transaction with metadata successfully.`);
98
+ // Return the transaction build result
99
+ return txBuildResult;
100
+ }
101
+ /**
102
+ * Build a multi-asset transaction
103
+ * @param req transaction build request
104
+ * @param protocolParameters current protocol parameters
105
+ * @returns {Promise<TxBuildResult>} transaction build result
106
+ */
107
+ async buildMultiAssetTransaction(req, protocolParameters) {
108
+ const builder = await this.ensureInitialized();
109
+ // Prepare the transaction build context
110
+ const utxos = await this._fetchUtxosForAddress(req.senderAddress);
111
+ logger.info(`Fetched ${utxos.length} UTxOs for multi-asset transaction`);
112
+ for (const u of utxos) {
113
+ logger.info(`UTxO ${u.txHash}:${u.outputIndex} amounts: ${JSON.stringify(u.amount)}`);
114
+ }
115
+ const txContext = {
116
+ utxos,
117
+ protocolParameters: protocolParameters
118
+ };
119
+ // Build the unsigned multi-asset transaction
120
+ const txBuildResult = await builder.buildUnsignedMultiAssetTransaction(req, txContext);
121
+ logger.info(`Built multi-asset transaction successfully.`);
122
+ // Return the transaction build result
123
+ return txBuildResult;
124
+ }
125
+ /**
126
+ * Build a minting transaction
127
+ * @param req transaction build request
128
+ * @param protocolParameters current protocol parameters
129
+ * @returns {Promise<TxBuildResult>} transaction build result
130
+ */
131
+ async buildMintTransaction(req, protocolParameters) {
132
+ // Validate mint-specific required fields
133
+ if (!req.mintActions || req.mintActions.length === 0) {
134
+ throw new Error('[CardanoTransactionBuilder] buildMintTransaction requires mintActions to be specified');
135
+ }
136
+ if (!req.mintingPolicyScript) {
137
+ throw new Error('[CardanoTransactionBuilder] buildMintTransaction requires mintingPolicyScript to be specified');
138
+ }
139
+ // Type is now narrowed to TxBuildMintRequest
140
+ const mintReq = req;
141
+ const builder = await this.ensureInitialized();
142
+ const cardanoClient = this.client;
143
+ // Prepare the transaction build context
144
+ const txContext = {
145
+ utxos: await this._fetchUtxosForAddress(req.senderAddress),
146
+ protocolParameters: protocolParameters,
147
+ // Pass evaluator if Ogmios is available for dynamic execution unit calculation
148
+ evaluateTransaction: cardanoClient.hasOgmiosBackend()
149
+ ? (cbor) => cardanoClient.evaluateTransaction(cbor)
150
+ : undefined
151
+ };
152
+ if (txContext.evaluateTransaction) {
153
+ logger.info(`Ogmios available - will use dynamic script evaluation`);
154
+ }
155
+ else {
156
+ logger.info(`Ogmios not available - using default execution units`);
157
+ }
158
+ // Build the unsigned minting transaction
159
+ const txBuildResult = await builder.buildUnsignedMintTransaction(mintReq, txContext);
160
+ logger.info(`Built minting transaction successfully.`);
161
+ // Return the transaction build result
162
+ return txBuildResult;
163
+ }
164
+ /**
165
+ * Build a Plutus spending transaction (consume UTxO at script address)
166
+ * @param req transaction build request
167
+ * @param protocolParameters current protocol parameters
168
+ * @returns {Promise<TxBuildResult>} transaction build result
169
+ */
170
+ async buildPlutusSpendTransaction(req, protocolParameters) {
171
+ if (!req.plutusScriptExecution) {
172
+ throw new Error('[CardanoTransactionBuilder] buildPlutusSpendTransaction requires plutusScriptExecution to be specified');
173
+ }
174
+ const spendReq = req;
175
+ const builder = await this.ensureInitialized();
176
+ const cardanoClient = this.client;
177
+ // Fetch sender UTxOs for fee payment
178
+ const senderUtxos = await this._fetchUtxosForAddress(req.senderAddress);
179
+ // Fetch the script UTxO separately (it's at the script address, not sender address)
180
+ // We include it in the UTxO set so the builder can find it
181
+ const scriptRef = spendReq.plutusScriptExecution.scriptUtxo;
182
+ const allUtxos = [...senderUtxos];
183
+ // Check if the script UTxO is already in sender UTxOs (unlikely but possible)
184
+ const alreadyIncluded = senderUtxos.some(u => u.txHash === scriptRef.txHash && u.outputIndex === scriptRef.outputIndex);
185
+ if (!alreadyIncluded) {
186
+ // Fetch script UTxO via transaction lookup - the backend needs to provide it
187
+ // For now, we create a minimal UTxO entry from what we know
188
+ // The actual UTxO data will be resolved by the backend during tx building
189
+ logger.info(`Script UTxO ${scriptRef.txHash}#${scriptRef.outputIndex} not in sender UTxOs - fetching from backend`);
190
+ const tx = await cardanoClient.getTransaction(scriptRef.txHash);
191
+ const scriptOutput = tx.outputs?.find(o => o.outputIndex === scriptRef.outputIndex);
192
+ if (!scriptOutput) {
193
+ throw new Error(`[CardanoTransactionBuilder] Script UTxO output ${scriptRef.txHash}#${scriptRef.outputIndex} not found in transaction`);
194
+ }
195
+ allUtxos.push({
196
+ txHash: scriptRef.txHash,
197
+ outputIndex: scriptRef.outputIndex,
198
+ address: scriptOutput.address,
199
+ amount: scriptOutput.amount,
200
+ });
201
+ }
202
+ const txContext = {
203
+ utxos: allUtxos,
204
+ protocolParameters: protocolParameters,
205
+ evaluateTransaction: cardanoClient.hasOgmiosBackend()
206
+ ? (cbor) => cardanoClient.evaluateTransaction(cbor)
207
+ : undefined
208
+ };
209
+ if (txContext.evaluateTransaction) {
210
+ logger.info(`Ogmios available - will use dynamic script evaluation`);
211
+ }
212
+ else {
213
+ logger.info(`Ogmios not available - using default execution units`);
214
+ }
215
+ const txBuildResult = await builder.buildUnsignedPlutusSpendTransaction(spendReq, txContext);
216
+ logger.info(`Built Plutus spending transaction successfully.`);
217
+ return txBuildResult;
218
+ }
219
+ /**
220
+ * Fetch UTxOs for a given address
221
+ * @param address bech32 address
222
+ * @returns {Promise<UTxO[]>} list of UTxOs
223
+ */
224
+ async _fetchUtxosForAddress(address) {
225
+ // fetch UTxOs directly using cardano client
226
+ logger.debug(`Fetching UTxOs for address: ${address}`);
227
+ const utxos = await this.client.getAddressUtxos(address);
228
+ return utxos;
229
+ }
230
+ }
231
+ exports.CardanoTransactionBuilder = CardanoTransactionBuilder;
232
+ //# sourceMappingURL=cardano-tx-builder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cardano-tx-builder.js","sourceRoot":"","sources":["cardano-tx-builder.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"circuit-breaker.d.ts","sourceRoot":"","sources":["circuit-breaker.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,MAAM,GAAG,WAAW,CAAC;AAE3D,MAAM,WAAW,oBAAoB;IACnC,iEAAiE;IACjE,gBAAgB,EAAE,MAAM,CAAC;IACzB,mEAAmE;IACnE,gBAAgB,EAAE,MAAM,CAAC;IACzB,8EAA8E;IAC9E,cAAc,EAAE,MAAM,CAAC;CACxB;AAeD;;;;;;;;GAQG;AACH,qBAAa,qBAAqB;IAChC,OAAO,CAAC,QAAQ,CAAmC;IACnD,OAAO,CAAC,MAAM,CAAuB;gBAEzB,MAAM,CAAC,EAAE,OAAO,CAAC,oBAAoB,CAAC;IAIlD;;;OAGG;IACH,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO;IAqB3C,6CAA6C;IAC7C,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI;IAkBxC,yCAAyC;IACzC,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI;IAqBxC,oDAAoD;IACpD,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,YAAY;IAY3C,8CAA8C;IAC9C,KAAK,IAAI,IAAI;CAGd"}
@@ -0,0 +1,110 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.CircuitBreakerManager = void 0;
7
+ const cds_1 = __importDefault(require("@sap/cds"));
8
+ const logger = cds_1.default.log('CircuitBreaker');
9
+ const DEFAULT_CONFIG = {
10
+ failureThreshold: 5,
11
+ successThreshold: 2,
12
+ resetTimeoutMs: 30_000,
13
+ };
14
+ /**
15
+ * Circuit Breaker for backend failover.
16
+ * Tracks per-backend failure counts and prevents hammering unhealthy backends.
17
+ *
18
+ * States:
19
+ * closed → normal operation, requests pass through
20
+ * open → backend is unhealthy, requests are skipped
21
+ * half-open → probe period, limited requests allowed to test recovery
22
+ */
23
+ class CircuitBreakerManager {
24
+ circuits = new Map();
25
+ config;
26
+ constructor(config) {
27
+ this.config = { ...DEFAULT_CONFIG, ...config };
28
+ }
29
+ /**
30
+ * Check if a backend should be attempted.
31
+ * Transitions open → half-open if reset timeout has elapsed.
32
+ */
33
+ shouldAttempt(backendName) {
34
+ const entry = this.circuits.get(backendName);
35
+ if (!entry)
36
+ return true; // no history = closed
37
+ if (entry.state === 'closed')
38
+ return true;
39
+ if (entry.state === 'open') {
40
+ const elapsed = Date.now() - entry.lastFailureTime;
41
+ if (elapsed >= this.config.resetTimeoutMs) {
42
+ entry.state = 'half-open';
43
+ entry.successes = 0;
44
+ logger.debug(`Circuit half-open for ${backendName} after ${elapsed}ms`);
45
+ return true;
46
+ }
47
+ return false;
48
+ }
49
+ // half-open: allow probe requests
50
+ return true;
51
+ }
52
+ /** Record a successful call to a backend. */
53
+ recordSuccess(backendName) {
54
+ const entry = this.circuits.get(backendName);
55
+ if (!entry)
56
+ return;
57
+ if (entry.state === 'half-open') {
58
+ entry.successes++;
59
+ if (entry.successes >= this.config.successThreshold) {
60
+ entry.state = 'closed';
61
+ entry.failures = 0;
62
+ entry.successes = 0;
63
+ logger.info(`Circuit closed for ${backendName} (recovered)`);
64
+ }
65
+ }
66
+ else if (entry.state === 'closed') {
67
+ // Reset failure count on success
68
+ entry.failures = 0;
69
+ }
70
+ }
71
+ /** Record a failed call to a backend. */
72
+ recordFailure(backendName) {
73
+ let entry = this.circuits.get(backendName);
74
+ if (!entry) {
75
+ entry = { state: 'closed', failures: 0, successes: 0, lastFailureTime: 0 };
76
+ this.circuits.set(backendName, entry);
77
+ }
78
+ entry.failures++;
79
+ entry.lastFailureTime = Date.now();
80
+ if (entry.state === 'half-open') {
81
+ // Any failure in half-open reopens the circuit
82
+ entry.state = 'open';
83
+ entry.successes = 0;
84
+ logger.warn(`Circuit re-opened for ${backendName} (failed during probe)`);
85
+ }
86
+ else if (entry.state === 'closed' && entry.failures >= this.config.failureThreshold) {
87
+ entry.state = 'open';
88
+ logger.warn(`Circuit opened for ${backendName} after ${entry.failures} failures`);
89
+ }
90
+ }
91
+ /** Get the current state of a backend's circuit. */
92
+ getState(backendName) {
93
+ const entry = this.circuits.get(backendName);
94
+ if (!entry)
95
+ return 'closed';
96
+ // Check for auto-transition to half-open
97
+ if (entry.state === 'open') {
98
+ const elapsed = Date.now() - entry.lastFailureTime;
99
+ if (elapsed >= this.config.resetTimeoutMs)
100
+ return 'half-open';
101
+ }
102
+ return entry.state;
103
+ }
104
+ /** Reset all circuit states (for testing). */
105
+ reset() {
106
+ this.circuits.clear();
107
+ }
108
+ }
109
+ exports.CircuitBreakerManager = CircuitBreakerManager;
110
+ //# sourceMappingURL=circuit-breaker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"circuit-breaker.js","sourceRoot":"","sources":["circuit-breaker.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"external-signer.d.ts","sourceRoot":"","sources":["external-signer.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAwB,MAAM,sBAAsB,CAAC;AAE/E,OAAO,EACL,kBAAkB,EAGlB,uBAAuB,EACvB,eAAe,EACf,oBAAoB,EACpB,2BAA2B,EAC3B,mBAAmB,EACpB,MAAM,mBAAmB,CAAC;AAS3B;;;;;;;;;;;;;GAaG;AACH,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,QAAQ,CAAoB;IACpC,OAAO,CAAC,YAAY,CAAS;gBAEjB,OAAO,CAAC,EAAE;QAAE,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE;IAK/C;;;;;;;;;;;;;OAaG;IACI,oBAAoB,CACzB,OAAO,EAAE,MAAM,EACf,cAAc,EAAE,MAAM,EACtB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE;QACR,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;QAC3B,cAAc,CAAC,EAAE,kBAAkB,CAAC;KACrC,GACA,uBAAuB;IAmC1B;;OAEG;IACH,OAAO,CAAC,2BAA2B;IAiBnC;;;;;;;;;;OAUG;IACI,uBAAuB,CAC5B,YAAY,EAAE,MAAM,EACpB,kBAAkB,EAAE,MAAM,EAC1B,OAAO,CAAC,EAAE,IAAI,CAAC,mBAAmB,EAAE,oBAAoB,CAAC,GAAG;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,GACjF,2BAA2B;IAqC9B;;;;;;;OAOG;IACI,aAAa,CAClB,YAAY,EAAE,MAAM,EACpB,kBAAkB,EAAE,MAAM,EAC1B,OAAO,CAAC,EAAE,IAAI,CAAC,mBAAmB,EAAE,oBAAoB,CAAC,GACxD,2BAA2B;IAY9B;;;;;;;;OAQG;IACI,mBAAmB,CAAC,cAAc,EAAE,uBAAuB,GAAG,oBAAoB;IAUzF;;;;;;OAMG;IACI,YAAY,CAAC,KAAK,EAAE,oBAAoB,EAAE,YAAY,EAAE,MAAM,GAAG,oBAAoB;IAY5F;;;;;;OAMG;IACI,cAAc,CACnB,KAAK,EAAE,oBAAoB,EAC3B,kBAAkB,EAAE,2BAA2B,GAC9C,oBAAoB;IAgBvB;;;;;;OAMG;IACI,eAAe,CAAC,KAAK,EAAE,oBAAoB,EAAE,MAAM,EAAE,MAAM,GAAG,oBAAoB;IAYzF;;;;;;OAMG;IACI,YAAY,CAAC,KAAK,EAAE,oBAAoB,EAAE,YAAY,EAAE,MAAM,GAAG,oBAAoB;IAY5F;;;;;OAKG;IACI,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO;IAI5C;;;;;;;;;;;;OAYG;IACI,qBAAqB,CAC1B,OAAO,EAAE,eAAe,EACxB,uBAAuB,EAAE,MAAM,GAC9B,2BAA2B;IAiB9B;;OAEG;IACI,WAAW,IAAI,iBAAiB;CAGxC;AAKD;;GAEG;AACH,wBAAgB,uBAAuB,IAAI,oBAAoB,CAK9D;AAED;;GAEG;AACH,wBAAgB,0BAA0B,CAAC,OAAO,CAAC,EAAE;IACnD,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,GAAG,oBAAoB,CAEvB"}
@@ -0,0 +1,302 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.ExternalSignerModule = void 0;
7
+ exports.getExternalSignerModule = getExternalSignerModule;
8
+ exports.createExternalSignerModule = createExternalSignerModule;
9
+ const cds_1 = __importDefault(require("@sap/cds"));
10
+ const signature_verifier_1 = require("./signature-verifier");
11
+ const errors_1 = require("../../utils/errors");
12
+ const types_1 = require("../../utils/types");
13
+ const logger = cds_1.default.log('ExternalSigner');
14
+ /**
15
+ * Default TTL for signing requests (30 minutes)
16
+ */
17
+ const DEFAULT_SIGNING_TTL_MS = 30 * 60 * 1000;
18
+ /**
19
+ * ExternalSignerModule - Manages the external signing workflow
20
+ *
21
+ * This module orchestrates the complete flow:
22
+ * 1. Create signing request from build result
23
+ * 2. Export unsigned transaction for external signing
24
+ * 3. Receive and verify signed transaction
25
+ * 4. Prepare for submission
26
+ *
27
+ * Key security principles:
28
+ * - NO private keys are ever handled by this service
29
+ * - Signature verification ensures transaction integrity
30
+ * - Complete audit trail of the signing workflow
31
+ */
32
+ class ExternalSignerModule {
33
+ verifier;
34
+ signingTtlMs;
35
+ constructor(options) {
36
+ this.verifier = (0, signature_verifier_1.getSignatureVerifier)();
37
+ this.signingTtlMs = options?.signingTtlMs ?? DEFAULT_SIGNING_TTL_MS;
38
+ }
39
+ /**
40
+ * Create an unsigned transaction export payload for external signing
41
+ *
42
+ * This is the entry point for the external signing workflow.
43
+ * Call this after building a transaction to get a standardized
44
+ * payload that external signers can use.
45
+ *
46
+ * @param buildId - The build ID from TransactionBuilds
47
+ * @param unsignedTxCbor - The unsigned transaction CBOR
48
+ * @param txBodyHash - The transaction body hash
49
+ * @param network - The Cardano network
50
+ * @param options - Additional options
51
+ * @returns Unsigned transaction export payload
52
+ */
53
+ createSigningRequest(buildId, unsignedTxCbor, txBodyHash, network, message, options) {
54
+ const signingRequestId = cds_1.default.utils.uuid();
55
+ const now = new Date();
56
+ const expiresAt = new Date(now.getTime() + this.signingTtlMs);
57
+ const signerTypeHint = options?.signerTypeHint ?? types_1.ExternalSignerType.CARDANO_CLI;
58
+ const payload = {
59
+ signingRequestId,
60
+ buildId,
61
+ txBodyHash,
62
+ unsignedTxCbor,
63
+ network,
64
+ createdAt: now.toISOString(),
65
+ expiresAt: expiresAt.toISOString(),
66
+ requiredSigners: options?.requiredSigners,
67
+ signingInstructions: this.generateSigningInstructions(unsignedTxCbor, network, message, signerTypeHint),
68
+ };
69
+ logger.info({
70
+ signingRequestId,
71
+ buildId,
72
+ txBodyHash,
73
+ network,
74
+ expiresAt: expiresAt.toISOString(),
75
+ }, 'Created signing request');
76
+ return payload;
77
+ }
78
+ /**
79
+ * Generate signing instructions for different signer types
80
+ */
81
+ generateSigningInstructions(unsignedTxCbor, network, message, signerTypeHint) {
82
+ return {
83
+ signerTypeHint,
84
+ message: message,
85
+ network,
86
+ cip30SigningRequest: {
87
+ txCbor: unsignedTxCbor,
88
+ partialSign: false,
89
+ },
90
+ };
91
+ }
92
+ /**
93
+ * Verify a signed transaction
94
+ *
95
+ * Call this after receiving a signed transaction from an external signer.
96
+ * This verifies the signature integrity before submission.
97
+ *
98
+ * @param signedTxCbor - The signed transaction CBOR
99
+ * @param expectedTxBodyHash - The expected transaction body hash (from the build)
100
+ * @param options - Additional verification options
101
+ * @returns Verification result
102
+ */
103
+ verifySignedTransaction(signedTxCbor, expectedTxBodyHash, options) {
104
+ logger.debug({ expectedTxBodyHash }, 'Verifying signed transaction');
105
+ // Enforce signing TTL if expiresAt is provided
106
+ if (options?.expiresAt && this.isExpired(options.expiresAt)) {
107
+ return {
108
+ isValid: false,
109
+ txBodyHash: '',
110
+ witnessCount: 0,
111
+ signerKeyHashes: [],
112
+ warnings: [],
113
+ errorMessage: 'Signing request has expired',
114
+ };
115
+ }
116
+ const result = this.verifier.verify(signedTxCbor, {
117
+ ...options,
118
+ expectedTxBodyHash,
119
+ requireSignature: true,
120
+ });
121
+ if (result.isValid) {
122
+ logger.info({
123
+ txBodyHash: result.txBodyHash,
124
+ witnessCount: result.witnessCount,
125
+ signers: result.signerKeyHashes,
126
+ }, 'Signature verification successful');
127
+ }
128
+ else {
129
+ logger.warn({
130
+ error: result.errorMessage,
131
+ warnings: result.warnings,
132
+ }, 'Signature verification failed');
133
+ }
134
+ return result;
135
+ }
136
+ /**
137
+ * Verify signed transaction and throw on failure
138
+ *
139
+ * @param signedTxCbor - The signed transaction CBOR
140
+ * @param expectedTxBodyHash - The expected transaction body hash
141
+ * @param options - Additional verification options
142
+ * @throws {TransactionValidationError} if verification fails
143
+ */
144
+ verifyOrThrow(signedTxCbor, expectedTxBodyHash, options) {
145
+ const result = this.verifySignedTransaction(signedTxCbor, expectedTxBodyHash, options);
146
+ if (!result.isValid) {
147
+ throw new errors_1.TransactionValidationError(result.errorMessage || 'Signature verification failed');
148
+ }
149
+ return result;
150
+ }
151
+ /**
152
+ * Create a complete signing workflow state
153
+ *
154
+ * This creates a trackable workflow state that can be stored
155
+ * and updated throughout the signing process.
156
+ *
157
+ * @param signingRequest - The unsigned transaction export payload
158
+ * @returns Initial workflow state
159
+ */
160
+ createWorkflowState(signingRequest) {
161
+ return {
162
+ status: types_1.SigningStatus.PENDING,
163
+ request: signingRequest,
164
+ timestamps: {
165
+ created: signingRequest.createdAt,
166
+ },
167
+ };
168
+ }
169
+ /**
170
+ * Update workflow state after signing
171
+ *
172
+ * @param state - Current workflow state
173
+ * @param signedTxCbor - The signed transaction CBOR
174
+ * @returns Updated workflow state
175
+ */
176
+ markAsSigned(state, signedTxCbor) {
177
+ return {
178
+ ...state,
179
+ status: types_1.SigningStatus.SIGNED,
180
+ signedTxCbor,
181
+ timestamps: {
182
+ ...state.timestamps,
183
+ signed: new Date().toISOString(),
184
+ },
185
+ };
186
+ }
187
+ /**
188
+ * Update workflow state after verification
189
+ *
190
+ * @param state - Current workflow state
191
+ * @param verificationResult - The verification result
192
+ * @returns Updated workflow state
193
+ */
194
+ markAsVerified(state, verificationResult) {
195
+ if (!verificationResult.isValid) {
196
+ return this.markAsFailed(state, String(verificationResult.errorMessage));
197
+ }
198
+ return {
199
+ ...state,
200
+ status: types_1.SigningStatus.VERIFIED,
201
+ verificationResult,
202
+ timestamps: {
203
+ ...state.timestamps,
204
+ verified: new Date().toISOString(),
205
+ },
206
+ };
207
+ }
208
+ /**
209
+ * Update workflow state after submission
210
+ *
211
+ * @param state - Current workflow state
212
+ * @param txHash - The submitted transaction hash
213
+ * @returns Updated workflow state
214
+ */
215
+ markAsSubmitted(state, txHash) {
216
+ return {
217
+ ...state,
218
+ status: types_1.SigningStatus.SUBMITTED,
219
+ txHash,
220
+ timestamps: {
221
+ ...state.timestamps,
222
+ submitted: new Date().toISOString(),
223
+ },
224
+ };
225
+ }
226
+ /**
227
+ * Update workflow state on failure
228
+ *
229
+ * @param state - Current workflow state
230
+ * @param errorMessage - The error message
231
+ * @returns Updated workflow state
232
+ */
233
+ markAsFailed(state, errorMessage) {
234
+ return {
235
+ ...state,
236
+ status: types_1.SigningStatus.FAILED,
237
+ errorMessage,
238
+ timestamps: {
239
+ ...state.timestamps,
240
+ failed: new Date().toISOString(),
241
+ },
242
+ };
243
+ }
244
+ /**
245
+ * Check if a signing request has expired
246
+ *
247
+ * @param expiresAt - The expiration timestamp (ISO 8601)
248
+ * @returns true if expired
249
+ */
250
+ isExpired(expiresAt) {
251
+ return new Date(expiresAt) < new Date();
252
+ }
253
+ /**
254
+ * Validate a signed transaction payload before submission
255
+ *
256
+ * This performs all pre-submission checks:
257
+ * 1. Verify the signature
258
+ * 2. Check transaction hasn't been tampered with
259
+ * 3. Ensure the build ID matches
260
+ *
261
+ * @param payload - The signed transaction payload
262
+ * @param originalBuildTxBodyHash - The original transaction body hash from the build
263
+ * @returns Validation result with verification details
264
+ * @throws {TransactionValidationError} if validation fails
265
+ */
266
+ validateForSubmission(payload, originalBuildTxBodyHash) {
267
+ // Verify the signature and transaction integrity
268
+ const result = this.verifyOrThrow(payload.signedTxCbor, originalBuildTxBodyHash);
269
+ logger.info({
270
+ signingRequestId: payload.signingRequestId,
271
+ buildId: payload.buildId,
272
+ signerType: payload.signerType,
273
+ witnessCount: result.witnessCount,
274
+ }, 'Transaction validated for submission');
275
+ return result;
276
+ }
277
+ /**
278
+ * Get the signature verifier instance
279
+ */
280
+ getVerifier() {
281
+ return this.verifier;
282
+ }
283
+ }
284
+ exports.ExternalSignerModule = ExternalSignerModule;
285
+ // Singleton instance
286
+ let moduleInstance = null;
287
+ /**
288
+ * Get the singleton ExternalSignerModule instance
289
+ */
290
+ function getExternalSignerModule() {
291
+ if (!moduleInstance) {
292
+ moduleInstance = new ExternalSignerModule();
293
+ }
294
+ return moduleInstance;
295
+ }
296
+ /**
297
+ * Create a new ExternalSignerModule instance with custom options
298
+ */
299
+ function createExternalSignerModule(options) {
300
+ return new ExternalSignerModule(options);
301
+ }
302
+ //# sourceMappingURL=external-signer.js.map