@psavelis/enterprise-blockchain 0.1.0 → 1.1.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.
- package/README.md +15 -2
- package/dist/aid-settlement/application/reconciler.d.ts +13 -0
- package/dist/aid-settlement/application/reconciler.d.ts.map +1 -0
- package/dist/aid-settlement/application/reconciler.js +77 -0
- package/dist/aid-settlement/domain/entities.d.ts +24 -0
- package/dist/aid-settlement/domain/entities.d.ts.map +1 -0
- package/dist/aid-settlement/domain/entities.js +1 -0
- package/dist/aid-settlement/domain/ports.d.ts +10 -0
- package/dist/aid-settlement/domain/ports.d.ts.map +1 -0
- package/dist/aid-settlement/domain/ports.js +1 -0
- package/dist/aid-settlement/index.d.ts +19 -0
- package/dist/aid-settlement/index.d.ts.map +1 -0
- package/dist/aid-settlement/index.js +23 -0
- package/dist/aid-settlement/infrastructure/in-memory-store.d.ts +12 -0
- package/dist/aid-settlement/infrastructure/in-memory-store.d.ts.map +1 -0
- package/dist/aid-settlement/infrastructure/in-memory-store.js +17 -0
- package/dist/credentialing/application/clearance-evaluator.d.ts +10 -0
- package/dist/credentialing/application/clearance-evaluator.d.ts.map +1 -0
- package/dist/credentialing/application/clearance-evaluator.js +63 -0
- package/dist/credentialing/domain/entities.d.ts +28 -0
- package/dist/credentialing/domain/entities.d.ts.map +1 -0
- package/dist/credentialing/domain/entities.js +1 -0
- package/dist/credentialing/domain/ports.d.ts +9 -0
- package/dist/credentialing/domain/ports.d.ts.map +1 -0
- package/dist/credentialing/domain/ports.js +1 -0
- package/dist/credentialing/index.d.ts +19 -0
- package/dist/credentialing/index.d.ts.map +1 -0
- package/dist/credentialing/index.js +23 -0
- package/dist/credentialing/infrastructure/in-memory-store.d.ts +11 -0
- package/dist/credentialing/infrastructure/in-memory-store.d.ts.map +1 -0
- package/dist/credentialing/infrastructure/in-memory-store.js +14 -0
- package/dist/hsm/application/asymmetric-key-service.d.ts +23 -0
- package/dist/hsm/application/asymmetric-key-service.d.ts.map +1 -0
- package/dist/hsm/application/asymmetric-key-service.js +109 -0
- package/dist/hsm/application/envelope-encryption-service.d.ts +18 -0
- package/dist/hsm/application/envelope-encryption-service.d.ts.map +1 -0
- package/dist/hsm/application/envelope-encryption-service.js +59 -0
- package/dist/hsm/application/symmetric-key-service.d.ts +34 -0
- package/dist/hsm/application/symmetric-key-service.d.ts.map +1 -0
- package/dist/hsm/application/symmetric-key-service.js +107 -0
- package/dist/hsm/domain/entities.d.ts +104 -0
- package/dist/hsm/domain/entities.d.ts.map +1 -0
- package/dist/hsm/domain/entities.js +10 -0
- package/dist/hsm/domain/ports.d.ts +20 -0
- package/dist/hsm/domain/ports.d.ts.map +1 -0
- package/dist/hsm/domain/ports.js +1 -0
- package/dist/hsm/index.d.ts +48 -0
- package/dist/hsm/index.d.ts.map +1 -0
- package/dist/hsm/index.js +97 -0
- package/dist/hsm/infrastructure/audit-log-factory.d.ts +59 -0
- package/dist/hsm/infrastructure/audit-log-factory.d.ts.map +1 -0
- package/dist/hsm/infrastructure/audit-log-factory.js +95 -0
- package/dist/hsm/infrastructure/audit-log.d.ts +8 -0
- package/dist/hsm/infrastructure/audit-log.d.ts.map +1 -0
- package/dist/hsm/infrastructure/audit-log.js +18 -0
- package/dist/hsm/infrastructure/file-audit-log.d.ts +55 -0
- package/dist/hsm/infrastructure/file-audit-log.d.ts.map +1 -0
- package/dist/hsm/infrastructure/file-audit-log.js +128 -0
- package/dist/hsm/infrastructure/key-store.d.ts +9 -0
- package/dist/hsm/infrastructure/key-store.d.ts.map +1 -0
- package/dist/hsm/infrastructure/key-store.js +12 -0
- package/dist/hsm/infrastructure/syslog-audit-log.d.ts +64 -0
- package/dist/hsm/infrastructure/syslog-audit-log.d.ts.map +1 -0
- package/dist/hsm/infrastructure/syslog-audit-log.js +167 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +37 -0
- package/dist/integrations/besu-client/error-mapper.d.ts +9 -0
- package/dist/integrations/besu-client/error-mapper.d.ts.map +1 -0
- package/dist/integrations/besu-client/error-mapper.js +22 -0
- package/dist/integrations/besu-client/index.d.ts +65 -0
- package/dist/integrations/besu-client/index.d.ts.map +1 -0
- package/dist/integrations/besu-client/index.js +276 -0
- package/dist/integrations/besu-client/ports.d.ts +44 -0
- package/dist/integrations/besu-client/ports.d.ts.map +1 -0
- package/dist/integrations/besu-client/ports.js +1 -0
- package/dist/integrations/corda-gateway/index.d.ts +37 -0
- package/dist/integrations/corda-gateway/index.d.ts.map +1 -0
- package/dist/integrations/corda-gateway/index.js +234 -0
- package/dist/integrations/corda-gateway/ports.d.ts +33 -0
- package/dist/integrations/corda-gateway/ports.d.ts.map +1 -0
- package/dist/integrations/corda-gateway/ports.js +1 -0
- package/dist/integrations/fabric-gateway/index.d.ts +78 -0
- package/dist/integrations/fabric-gateway/index.d.ts.map +1 -0
- package/dist/integrations/fabric-gateway/index.js +214 -0
- package/dist/integrations/fabric-gateway/ports.d.ts +50 -0
- package/dist/integrations/fabric-gateway/ports.d.ts.map +1 -0
- package/dist/integrations/fabric-gateway/ports.js +1 -0
- package/dist/integrations/index.d.ts +19 -0
- package/dist/integrations/index.d.ts.map +1 -0
- package/dist/integrations/index.js +19 -0
- package/dist/integrations/shared/env.d.ts +4 -0
- package/dist/integrations/shared/env.d.ts.map +1 -0
- package/dist/integrations/shared/env.js +24 -0
- package/dist/integrations/shared/retry.d.ts +79 -0
- package/dist/integrations/shared/retry.d.ts.map +1 -0
- package/dist/integrations/shared/retry.js +315 -0
- package/dist/mpc/adapters.d.ts +36 -0
- package/dist/mpc/adapters.d.ts.map +1 -0
- package/dist/mpc/adapters.js +46 -0
- package/dist/mpc/crypto.d.ts +2 -0
- package/dist/mpc/crypto.d.ts.map +1 -0
- package/dist/mpc/crypto.js +2 -0
- package/dist/mpc/dsa.d.ts +134 -0
- package/dist/mpc/dsa.d.ts.map +1 -0
- package/dist/mpc/dsa.js +127 -0
- package/dist/mpc/field.d.ts +127 -0
- package/dist/mpc/field.d.ts.map +1 -0
- package/dist/mpc/field.js +209 -0
- package/dist/mpc/hybrid-kem.d.ts +96 -0
- package/dist/mpc/hybrid-kem.d.ts.map +1 -0
- package/dist/mpc/hybrid-kem.js +136 -0
- package/dist/mpc/index.d.ts +135 -0
- package/dist/mpc/index.d.ts.map +1 -0
- package/dist/mpc/index.js +348 -0
- package/dist/mpc/kyber.d.ts +134 -0
- package/dist/mpc/kyber.d.ts.map +1 -0
- package/dist/mpc/kyber.js +143 -0
- package/dist/mpc/ports.d.ts +67 -0
- package/dist/mpc/ports.d.ts.map +1 -0
- package/dist/mpc/ports.js +9 -0
- package/dist/mpc/quantum.d.ts +80 -0
- package/dist/mpc/quantum.d.ts.map +1 -0
- package/dist/mpc/quantum.js +180 -0
- package/dist/p2mr/adapters.d.ts +31 -0
- package/dist/p2mr/adapters.d.ts.map +1 -0
- package/dist/p2mr/adapters.js +35 -0
- package/dist/p2mr/index.d.ts +63 -0
- package/dist/p2mr/index.d.ts.map +1 -0
- package/dist/p2mr/index.js +59 -0
- package/dist/p2mr/merkle-tree.d.ts +109 -0
- package/dist/p2mr/merkle-tree.d.ts.map +1 -0
- package/dist/p2mr/merkle-tree.js +239 -0
- package/dist/p2mr/p2mr-output.d.ts +142 -0
- package/dist/p2mr/p2mr-output.d.ts.map +1 -0
- package/dist/p2mr/p2mr-output.js +150 -0
- package/dist/p2mr/ports.d.ts +52 -0
- package/dist/p2mr/ports.d.ts.map +1 -0
- package/dist/p2mr/ports.js +9 -0
- package/dist/p2mr/script-interpreter.d.ts +92 -0
- package/dist/p2mr/script-interpreter.d.ts.map +1 -0
- package/dist/p2mr/script-interpreter.js +535 -0
- package/dist/p2mr/script-leaf.d.ts +70 -0
- package/dist/p2mr/script-leaf.d.ts.map +1 -0
- package/dist/p2mr/script-leaf.js +203 -0
- package/dist/p2mr/spend-proof.d.ts +95 -0
- package/dist/p2mr/spend-proof.d.ts.map +1 -0
- package/dist/p2mr/spend-proof.js +358 -0
- package/dist/p2mr/types.d.ts +209 -0
- package/dist/p2mr/types.d.ts.map +1 -0
- package/dist/p2mr/types.js +9 -0
- package/dist/privacy/application/view-projector.d.ts +13 -0
- package/dist/privacy/application/view-projector.d.ts.map +1 -0
- package/dist/privacy/application/view-projector.js +85 -0
- package/dist/privacy/domain/entities.d.ts +26 -0
- package/dist/privacy/domain/entities.d.ts.map +1 -0
- package/dist/privacy/domain/entities.js +1 -0
- package/dist/privacy/domain/ports.d.ts +7 -0
- package/dist/privacy/domain/ports.d.ts.map +1 -0
- package/dist/privacy/domain/ports.js +1 -0
- package/dist/privacy/index.d.ts +21 -0
- package/dist/privacy/index.d.ts.map +1 -0
- package/dist/privacy/index.js +25 -0
- package/dist/privacy/infrastructure/in-memory-store.d.ts +8 -0
- package/dist/privacy/infrastructure/in-memory-store.d.ts.map +1 -0
- package/dist/privacy/infrastructure/in-memory-store.js +7 -0
- package/dist/protocols/besu-port.d.ts +80 -0
- package/dist/protocols/besu-port.d.ts.map +1 -0
- package/dist/protocols/besu-port.js +1 -0
- package/dist/protocols/corda-port.d.ts +103 -0
- package/dist/protocols/corda-port.d.ts.map +1 -0
- package/dist/protocols/corda-port.js +9 -0
- package/dist/protocols/credentialing-port.d.ts +11 -0
- package/dist/protocols/credentialing-port.d.ts.map +1 -0
- package/dist/protocols/credentialing-port.js +1 -0
- package/dist/protocols/fabric-port.d.ts +89 -0
- package/dist/protocols/fabric-port.d.ts.map +1 -0
- package/dist/protocols/fabric-port.js +9 -0
- package/dist/protocols/index.d.ts +14 -0
- package/dist/protocols/index.d.ts.map +1 -0
- package/dist/protocols/index.js +7 -0
- package/dist/protocols/p2mr-port.d.ts +159 -0
- package/dist/protocols/p2mr-port.d.ts.map +1 -0
- package/dist/protocols/p2mr-port.js +12 -0
- package/dist/protocols/privacy-port.d.ts +9 -0
- package/dist/protocols/privacy-port.d.ts.map +1 -0
- package/dist/protocols/privacy-port.js +1 -0
- package/dist/protocols/traceability-port.d.ts +12 -0
- package/dist/protocols/traceability-port.d.ts.map +1 -0
- package/dist/protocols/traceability-port.js +1 -0
- package/dist/shared/collection-store.d.ts +12 -0
- package/dist/shared/collection-store.d.ts.map +1 -0
- package/dist/shared/collection-store.js +26 -0
- package/dist/shared/commit.d.ts +24 -0
- package/dist/shared/commit.d.ts.map +1 -0
- package/dist/shared/commit.js +50 -0
- package/dist/shared/crypto.d.ts +2 -0
- package/dist/shared/crypto.d.ts.map +1 -0
- package/dist/shared/crypto.js +4 -0
- package/dist/shared/date.d.ts +2 -0
- package/dist/shared/date.d.ts.map +1 -0
- package/dist/shared/date.js +3 -0
- package/dist/shared/index.d.ts +9 -0
- package/dist/shared/index.d.ts.map +1 -0
- package/dist/shared/index.js +11 -0
- package/dist/shared/logger.d.ts +37 -0
- package/dist/shared/logger.d.ts.map +1 -0
- package/dist/shared/logger.js +45 -0
- package/dist/shared/store.d.ts +25 -0
- package/dist/shared/store.d.ts.map +1 -0
- package/dist/shared/store.js +18 -0
- package/dist/shared/telemetry-sdk.d.ts +26 -0
- package/dist/shared/telemetry-sdk.d.ts.map +1 -0
- package/dist/shared/telemetry-sdk.js +97 -0
- package/dist/shared/telemetry.d.ts +86 -0
- package/dist/shared/telemetry.d.ts.map +1 -0
- package/dist/shared/telemetry.js +137 -0
- package/dist/stark-settlement/application/aggregator-service.d.ts +112 -0
- package/dist/stark-settlement/application/aggregator-service.d.ts.map +1 -0
- package/dist/stark-settlement/application/aggregator-service.js +256 -0
- package/dist/stark-settlement/application/ledger-service.d.ts +114 -0
- package/dist/stark-settlement/application/ledger-service.d.ts.map +1 -0
- package/dist/stark-settlement/application/ledger-service.js +318 -0
- package/dist/stark-settlement/application/settlement-service.d.ts +104 -0
- package/dist/stark-settlement/application/settlement-service.d.ts.map +1 -0
- package/dist/stark-settlement/application/settlement-service.js +251 -0
- package/dist/stark-settlement/domain/entities.d.ts +365 -0
- package/dist/stark-settlement/domain/entities.d.ts.map +1 -0
- package/dist/stark-settlement/domain/entities.js +29 -0
- package/dist/stark-settlement/domain/ports.d.ts +485 -0
- package/dist/stark-settlement/domain/ports.d.ts.map +1 -0
- package/dist/stark-settlement/domain/ports.js +14 -0
- package/dist/stark-settlement/domain/value-objects.d.ts +268 -0
- package/dist/stark-settlement/domain/value-objects.d.ts.map +1 -0
- package/dist/stark-settlement/domain/value-objects.js +500 -0
- package/dist/stark-settlement/index.d.ts +172 -0
- package/dist/stark-settlement/index.d.ts.map +1 -0
- package/dist/stark-settlement/index.js +193 -0
- package/dist/stark-settlement/infrastructure/adapters/audit-adapter.d.ts +52 -0
- package/dist/stark-settlement/infrastructure/adapters/audit-adapter.d.ts.map +1 -0
- package/dist/stark-settlement/infrastructure/adapters/audit-adapter.js +154 -0
- package/dist/stark-settlement/infrastructure/adapters/bitcoin-adapter.d.ts +88 -0
- package/dist/stark-settlement/infrastructure/adapters/bitcoin-adapter.d.ts.map +1 -0
- package/dist/stark-settlement/infrastructure/adapters/bitcoin-adapter.js +187 -0
- package/dist/stark-settlement/infrastructure/adapters/clock-adapter.d.ts +59 -0
- package/dist/stark-settlement/infrastructure/adapters/clock-adapter.d.ts.map +1 -0
- package/dist/stark-settlement/infrastructure/adapters/clock-adapter.js +85 -0
- package/dist/stark-settlement/infrastructure/adapters/dilithium-adapter.d.ts +60 -0
- package/dist/stark-settlement/infrastructure/adapters/dilithium-adapter.d.ts.map +1 -0
- package/dist/stark-settlement/infrastructure/adapters/dilithium-adapter.js +104 -0
- package/dist/stark-settlement/infrastructure/adapters/event-emitter-adapter.d.ts +115 -0
- package/dist/stark-settlement/infrastructure/adapters/event-emitter-adapter.d.ts.map +1 -0
- package/dist/stark-settlement/infrastructure/adapters/event-emitter-adapter.js +191 -0
- package/dist/stark-settlement/infrastructure/adapters/fiat-adapter.d.ts +65 -0
- package/dist/stark-settlement/infrastructure/adapters/fiat-adapter.d.ts.map +1 -0
- package/dist/stark-settlement/infrastructure/adapters/fiat-adapter.js +207 -0
- package/dist/stark-settlement/infrastructure/adapters/mock-stark-adapter.d.ts +73 -0
- package/dist/stark-settlement/infrastructure/adapters/mock-stark-adapter.d.ts.map +1 -0
- package/dist/stark-settlement/infrastructure/adapters/mock-stark-adapter.js +287 -0
- package/dist/stark-settlement/infrastructure/adapters/solana-adapter.d.ts +78 -0
- package/dist/stark-settlement/infrastructure/adapters/solana-adapter.d.ts.map +1 -0
- package/dist/stark-settlement/infrastructure/adapters/solana-adapter.js +172 -0
- package/dist/stark-settlement/infrastructure/adapters/starknet-proof-adapter.d.ts +56 -0
- package/dist/stark-settlement/infrastructure/adapters/starknet-proof-adapter.d.ts.map +1 -0
- package/dist/stark-settlement/infrastructure/adapters/starknet-proof-adapter.js +261 -0
- package/dist/stark-settlement/infrastructure/adapters/stone-proof-adapter.d.ts +125 -0
- package/dist/stark-settlement/infrastructure/adapters/stone-proof-adapter.d.ts.map +1 -0
- package/dist/stark-settlement/infrastructure/adapters/stone-proof-adapter.js +416 -0
- package/dist/stark-settlement/infrastructure/persistence/ledger-store.d.ts +68 -0
- package/dist/stark-settlement/infrastructure/persistence/ledger-store.d.ts.map +1 -0
- package/dist/stark-settlement/infrastructure/persistence/ledger-store.js +238 -0
- package/dist/stark-settlement/infrastructure/persistence/offset-store.d.ts +30 -0
- package/dist/stark-settlement/infrastructure/persistence/offset-store.d.ts.map +1 -0
- package/dist/stark-settlement/infrastructure/persistence/offset-store.js +57 -0
- package/dist/stark-settlement/infrastructure/persistence/outbox-store.d.ts +45 -0
- package/dist/stark-settlement/infrastructure/persistence/outbox-store.d.ts.map +1 -0
- package/dist/stark-settlement/infrastructure/persistence/outbox-store.js +171 -0
- package/dist/traceability/application/recall-assessor.d.ts +13 -0
- package/dist/traceability/application/recall-assessor.d.ts.map +1 -0
- package/dist/traceability/application/recall-assessor.js +74 -0
- package/dist/traceability/domain/entities.d.ts +23 -0
- package/dist/traceability/domain/entities.d.ts.map +1 -0
- package/dist/traceability/domain/entities.js +1 -0
- package/dist/traceability/domain/ports.d.ts +23 -0
- package/dist/traceability/domain/ports.d.ts.map +1 -0
- package/dist/traceability/domain/ports.js +1 -0
- package/dist/traceability/domain/recall.d.ts +12 -0
- package/dist/traceability/domain/recall.d.ts.map +1 -0
- package/dist/traceability/domain/recall.js +1 -0
- package/dist/traceability/index.d.ts +22 -0
- package/dist/traceability/index.d.ts.map +1 -0
- package/dist/traceability/index.js +26 -0
- package/dist/traceability/infrastructure/in-memory-store.d.ts +13 -0
- package/dist/traceability/infrastructure/in-memory-store.d.ts.map +1 -0
- package/dist/traceability/infrastructure/in-memory-store.js +24 -0
- package/package.json +12 -9
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/integrations/besu-client/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
import { Contract, Interface, JsonRpcProvider, NonceManager, Wallet, } from "ethers";
|
|
2
|
+
import consortiumRegistryArtifact from "../../../../../contracts/ConsortiumOrderRegistry.json";
|
|
3
|
+
import { getOptionalEnv, getNumberEnv, getRequiredEnv } from "../shared/env.js";
|
|
4
|
+
import { CircuitBreaker, BESU_RETRY_POLICY, BESU_NON_RETRYABLE, withRetry, } from "../shared/retry.js";
|
|
5
|
+
import { createTracer, withSpan, TelemetryAttributes, } from "../../shared/telemetry.js";
|
|
6
|
+
import { extractErrorMessage, extractErrorCode, isInsufficientFunds, isNonceTooLow, } from "./error-mapper.js";
|
|
7
|
+
const tracer = createTracer("besu-client");
|
|
8
|
+
const consortiumInterface = new Interface(consortiumRegistryArtifact.abi);
|
|
9
|
+
export class BesuProfileFactory {
|
|
10
|
+
createProfileFromEnv(env = process.env) {
|
|
11
|
+
const profile = {
|
|
12
|
+
rpcUrl: getRequiredEnv("BESU_RPC_URL", env),
|
|
13
|
+
chainId: getNumberEnv("BESU_CHAIN_ID", 1337, env),
|
|
14
|
+
contractAddress: getRequiredEnv("BESU_CONTRACT_ADDRESS", env),
|
|
15
|
+
};
|
|
16
|
+
const walletPrivateKey = getOptionalEnv("BESU_WALLET_PRIVATE_KEY", env);
|
|
17
|
+
if (walletPrivateKey) {
|
|
18
|
+
profile.walletPrivateKey = walletPrivateKey;
|
|
19
|
+
}
|
|
20
|
+
const privacyGroupId = getOptionalEnv("BESU_PRIVACY_GROUP_ID", env);
|
|
21
|
+
if (privacyGroupId) {
|
|
22
|
+
profile.privacyGroupId = privacyGroupId;
|
|
23
|
+
}
|
|
24
|
+
return profile;
|
|
25
|
+
}
|
|
26
|
+
createProfile(profile) {
|
|
27
|
+
if (!profile.rpcUrl.startsWith("http")) {
|
|
28
|
+
throw new Error("BesuRpcProfile.rpcUrl must be an HTTP(S) URL");
|
|
29
|
+
}
|
|
30
|
+
if (profile.chainId <= 0) {
|
|
31
|
+
throw new Error("BesuRpcProfile.chainId must be a positive integer");
|
|
32
|
+
}
|
|
33
|
+
return profile;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
export class BesuProviderFactory {
|
|
37
|
+
createProvider(profile) {
|
|
38
|
+
return new JsonRpcProvider(profile.rpcUrl, profile.chainId);
|
|
39
|
+
}
|
|
40
|
+
createSigner(profile) {
|
|
41
|
+
if (!profile.walletPrivateKey) {
|
|
42
|
+
throw new Error("walletPrivateKey is required to create a Besu signer");
|
|
43
|
+
}
|
|
44
|
+
return new Wallet(profile.walletPrivateKey, this.createProvider(profile));
|
|
45
|
+
}
|
|
46
|
+
createManagedSigner(profile) {
|
|
47
|
+
return new NonceManager(this.createSigner(profile));
|
|
48
|
+
}
|
|
49
|
+
createContract(profile, runner) {
|
|
50
|
+
const resolvedRunner = runner ?? this.createProvider(profile);
|
|
51
|
+
return new Contract(profile.contractAddress, consortiumRegistryArtifact.abi, resolvedRunner);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
export class BesuGasEstimator {
|
|
55
|
+
providerFactory;
|
|
56
|
+
constructor(providerFactory) {
|
|
57
|
+
this.providerFactory = providerFactory;
|
|
58
|
+
}
|
|
59
|
+
async estimateGas(profile, tx, gasLimitOverride) {
|
|
60
|
+
return withSpan(tracer, "besu.estimateGas", async (span) => {
|
|
61
|
+
span.setAttribute(TelemetryAttributes.BLOCKCHAIN_PLATFORM, "besu");
|
|
62
|
+
span.setAttribute("besu.chain_id", profile.chainId);
|
|
63
|
+
if (gasLimitOverride !== undefined) {
|
|
64
|
+
span.setAttribute("besu.gas_limit_override", gasLimitOverride.toString());
|
|
65
|
+
return gasLimitOverride;
|
|
66
|
+
}
|
|
67
|
+
try {
|
|
68
|
+
const gasEstimate = await this.providerFactory
|
|
69
|
+
.createProvider(profile)
|
|
70
|
+
.estimateGas(tx);
|
|
71
|
+
span.setAttribute("besu.gas_estimate", gasEstimate.toString());
|
|
72
|
+
return gasEstimate;
|
|
73
|
+
}
|
|
74
|
+
catch (err) {
|
|
75
|
+
const msg = extractErrorMessage(err);
|
|
76
|
+
span.setAttribute(TelemetryAttributes.ERROR_MESSAGE, msg);
|
|
77
|
+
if (isInsufficientFunds(err)) {
|
|
78
|
+
throw new Error(`Besu gas estimation failed — sender account has insufficient funds: ${msg}`, { cause: err });
|
|
79
|
+
}
|
|
80
|
+
throw new Error(`Besu gas estimation failed: ${msg}`, { cause: err });
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
export class BesuTransactionBuilder {
|
|
86
|
+
buildAnchorOrderTransaction(profile, order, auditProof, gasLimit) {
|
|
87
|
+
const tx = {
|
|
88
|
+
to: profile.contractAddress,
|
|
89
|
+
chainId: profile.chainId,
|
|
90
|
+
data: consortiumInterface.encodeFunctionData("anchorOrder", [
|
|
91
|
+
order.id,
|
|
92
|
+
order.buyer,
|
|
93
|
+
order.supplier,
|
|
94
|
+
auditProof,
|
|
95
|
+
]),
|
|
96
|
+
};
|
|
97
|
+
if (gasLimit !== undefined) {
|
|
98
|
+
tx.gasLimit = gasLimit;
|
|
99
|
+
}
|
|
100
|
+
return tx;
|
|
101
|
+
}
|
|
102
|
+
buildAudienceViewTransaction(profile, view, gasLimit) {
|
|
103
|
+
if (!profile.privacyGroupId) {
|
|
104
|
+
throw new Error("privacyGroupId is required to build a Besu private transaction");
|
|
105
|
+
}
|
|
106
|
+
const proofArg = typeof view.auditProof === "string"
|
|
107
|
+
? view.auditProof
|
|
108
|
+
: JSON.stringify(view.auditProof);
|
|
109
|
+
const tx = {
|
|
110
|
+
to: profile.contractAddress,
|
|
111
|
+
chainId: profile.chainId,
|
|
112
|
+
data: consortiumInterface.encodeFunctionData("publishAudienceView", [
|
|
113
|
+
view.orderId,
|
|
114
|
+
view.audience,
|
|
115
|
+
JSON.stringify(view.data),
|
|
116
|
+
proofArg,
|
|
117
|
+
]),
|
|
118
|
+
};
|
|
119
|
+
if (gasLimit !== undefined) {
|
|
120
|
+
tx.gasLimit = gasLimit;
|
|
121
|
+
}
|
|
122
|
+
return {
|
|
123
|
+
privacyGroupId: profile.privacyGroupId,
|
|
124
|
+
transaction: tx,
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
export class BesuTransactionSender {
|
|
129
|
+
async sendTransaction(signer, tx) {
|
|
130
|
+
return withSpan(tracer, "besu.sendTransaction", async (span) => {
|
|
131
|
+
span.setAttribute(TelemetryAttributes.BLOCKCHAIN_PLATFORM, "besu");
|
|
132
|
+
if (tx.to && typeof tx.to === "string") {
|
|
133
|
+
span.setAttribute("besu.to", tx.to);
|
|
134
|
+
}
|
|
135
|
+
if (tx.chainId)
|
|
136
|
+
span.setAttribute("besu.chain_id", Number(tx.chainId));
|
|
137
|
+
try {
|
|
138
|
+
const response = await signer.sendTransaction(tx);
|
|
139
|
+
span.setAttribute(TelemetryAttributes.BLOCKCHAIN_TX_ID, response.hash);
|
|
140
|
+
return response.hash;
|
|
141
|
+
}
|
|
142
|
+
catch (err) {
|
|
143
|
+
const msg = extractErrorMessage(err);
|
|
144
|
+
span.setAttribute(TelemetryAttributes.ERROR_MESSAGE, msg);
|
|
145
|
+
if (isNonceTooLow(err)) {
|
|
146
|
+
throw new Error(`Besu NONCE_TOO_LOW — another transaction from this account was mined first. ` +
|
|
147
|
+
`Retry with a fresh nonce or use createManagedSigner() for automatic sequencing.`, { cause: err });
|
|
148
|
+
}
|
|
149
|
+
if (isInsufficientFunds(err)) {
|
|
150
|
+
throw new Error(`Besu INSUFFICIENT_FUNDS — the sender account cannot cover gas × gasPrice. ` +
|
|
151
|
+
`Fund the account or lower gasLimit.`, { cause: err });
|
|
152
|
+
}
|
|
153
|
+
throw err;
|
|
154
|
+
}
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
export class BesuHealthChecker {
|
|
159
|
+
providerFactory;
|
|
160
|
+
constructor(providerFactory) {
|
|
161
|
+
this.providerFactory = providerFactory;
|
|
162
|
+
}
|
|
163
|
+
async checkHealth(profile) {
|
|
164
|
+
return withSpan(tracer, "besu.checkHealth", async (span) => {
|
|
165
|
+
span.setAttribute(TelemetryAttributes.BLOCKCHAIN_PLATFORM, "besu");
|
|
166
|
+
span.setAttribute("besu.chain_id", profile.chainId);
|
|
167
|
+
const start = Date.now();
|
|
168
|
+
try {
|
|
169
|
+
const provider = this.providerFactory.createProvider(profile);
|
|
170
|
+
const [blockNumber, network] = await Promise.all([
|
|
171
|
+
provider.getBlockNumber(),
|
|
172
|
+
provider.getNetwork(),
|
|
173
|
+
]);
|
|
174
|
+
const latencyMs = Date.now() - start;
|
|
175
|
+
span.setAttribute("besu.healthy", true);
|
|
176
|
+
span.setAttribute("besu.block_number", blockNumber.toString());
|
|
177
|
+
span.setAttribute("besu.latency_ms", latencyMs);
|
|
178
|
+
return {
|
|
179
|
+
healthy: true,
|
|
180
|
+
blockNumber: BigInt(blockNumber),
|
|
181
|
+
chainId: Number(network.chainId),
|
|
182
|
+
latencyMs,
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
catch (err) {
|
|
186
|
+
const latencyMs = Date.now() - start;
|
|
187
|
+
const errorMsg = extractErrorMessage(err);
|
|
188
|
+
span.setAttribute("besu.healthy", false);
|
|
189
|
+
span.setAttribute("besu.latency_ms", latencyMs);
|
|
190
|
+
span.setAttribute(TelemetryAttributes.ERROR_MESSAGE, errorMsg);
|
|
191
|
+
return {
|
|
192
|
+
healthy: false,
|
|
193
|
+
latencyMs,
|
|
194
|
+
error: errorMsg,
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Resilient Besu client with circuit breaker and retry support.
|
|
202
|
+
*
|
|
203
|
+
* Circuit breaker prevents cascading failures when Besu RPC is unavailable.
|
|
204
|
+
* Retry policy handles transient errors (SERVER_ERROR, TIMEOUT) with backoff.
|
|
205
|
+
*
|
|
206
|
+
* NOTE: sketch only — do not store key material as plain strings in production
|
|
207
|
+
*/
|
|
208
|
+
export class BesuEthersClientSketch {
|
|
209
|
+
profileFactory = new BesuProfileFactory();
|
|
210
|
+
providerFactory = new BesuProviderFactory();
|
|
211
|
+
txBuilder = new BesuTransactionBuilder();
|
|
212
|
+
txSender = new BesuTransactionSender();
|
|
213
|
+
healthChecker = new BesuHealthChecker(this.providerFactory);
|
|
214
|
+
circuitBreaker;
|
|
215
|
+
constructor(circuitBreakerOptions) {
|
|
216
|
+
this.circuitBreaker = new CircuitBreaker(circuitBreakerOptions, "besu-rpc");
|
|
217
|
+
}
|
|
218
|
+
createProfileFromEnv(env) {
|
|
219
|
+
return this.profileFactory.createProfileFromEnv(env);
|
|
220
|
+
}
|
|
221
|
+
createProfile(profile) {
|
|
222
|
+
return this.profileFactory.createProfile(profile);
|
|
223
|
+
}
|
|
224
|
+
createProvider(profile) {
|
|
225
|
+
return this.providerFactory.createProvider(profile);
|
|
226
|
+
}
|
|
227
|
+
createSigner(profile) {
|
|
228
|
+
return this.providerFactory.createSigner(profile);
|
|
229
|
+
}
|
|
230
|
+
createManagedSigner(profile) {
|
|
231
|
+
return this.providerFactory.createManagedSigner(profile);
|
|
232
|
+
}
|
|
233
|
+
createContract(profile, runner) {
|
|
234
|
+
return this.providerFactory.createContract(profile, runner);
|
|
235
|
+
}
|
|
236
|
+
async estimateGas(profile, tx, gasLimitOverride) {
|
|
237
|
+
if (gasLimitOverride !== undefined) {
|
|
238
|
+
return gasLimitOverride;
|
|
239
|
+
}
|
|
240
|
+
return this.circuitBreaker.execute(() => withRetry(async () => {
|
|
241
|
+
try {
|
|
242
|
+
return await this.createProvider(profile).estimateGas(tx);
|
|
243
|
+
}
|
|
244
|
+
catch (err) {
|
|
245
|
+
const msg = extractErrorMessage(err);
|
|
246
|
+
if (isInsufficientFunds(err)) {
|
|
247
|
+
throw new Error(`Besu gas estimation failed — sender account has insufficient funds: ${msg}`, { cause: err });
|
|
248
|
+
}
|
|
249
|
+
throw new Error(`Besu gas estimation failed: ${msg}`, {
|
|
250
|
+
cause: err,
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
}, BESU_RETRY_POLICY, BESU_NON_RETRYABLE, extractErrorCode, "besu.estimateGas"));
|
|
254
|
+
}
|
|
255
|
+
buildAnchorOrderTransaction(profile, order, auditProof, gasLimit) {
|
|
256
|
+
return this.txBuilder.buildAnchorOrderTransaction(profile, order, auditProof, gasLimit);
|
|
257
|
+
}
|
|
258
|
+
buildAudienceViewTransaction(profile, view, gasLimit) {
|
|
259
|
+
return this.txBuilder.buildAudienceViewTransaction(profile, view, gasLimit);
|
|
260
|
+
}
|
|
261
|
+
sendTransaction(signer, tx) {
|
|
262
|
+
return this.txSender.sendTransaction(signer, tx);
|
|
263
|
+
}
|
|
264
|
+
async checkHealth(profile) {
|
|
265
|
+
// Health checks bypass circuit breaker to allow probing during recovery
|
|
266
|
+
return this.healthChecker.checkHealth(profile);
|
|
267
|
+
}
|
|
268
|
+
/** Get circuit breaker state for monitoring dashboards. */
|
|
269
|
+
getCircuitBreakerHealth() {
|
|
270
|
+
return this.circuitBreaker.getHealthStatus();
|
|
271
|
+
}
|
|
272
|
+
/** Reset circuit breaker (use after resolving underlying issues). */
|
|
273
|
+
resetCircuitBreaker() {
|
|
274
|
+
this.circuitBreaker.reset();
|
|
275
|
+
}
|
|
276
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { Contract, JsonRpcProvider, NonceManager, TransactionRequest, Wallet } from "ethers";
|
|
2
|
+
import type { PurchaseOrder, SharedOrderView } from "../../privacy/domain/entities.js";
|
|
3
|
+
export interface BesuRpcProfile {
|
|
4
|
+
rpcUrl: string;
|
|
5
|
+
chainId: number;
|
|
6
|
+
contractAddress: string;
|
|
7
|
+
walletPrivateKey?: string;
|
|
8
|
+
privacyGroupId?: string;
|
|
9
|
+
}
|
|
10
|
+
export interface BesuPrivateTransactionRequest {
|
|
11
|
+
transaction: TransactionRequest;
|
|
12
|
+
privacyGroupId: string;
|
|
13
|
+
}
|
|
14
|
+
export interface IBesuProfileFactory {
|
|
15
|
+
createProfileFromEnv(env?: NodeJS.ProcessEnv): BesuRpcProfile;
|
|
16
|
+
createProfile(profile: BesuRpcProfile): BesuRpcProfile;
|
|
17
|
+
}
|
|
18
|
+
export interface IBesuProviderFactory {
|
|
19
|
+
createProvider(profile: BesuRpcProfile): JsonRpcProvider;
|
|
20
|
+
createSigner(profile: BesuRpcProfile): Wallet;
|
|
21
|
+
createManagedSigner(profile: BesuRpcProfile): NonceManager;
|
|
22
|
+
createContract(profile: BesuRpcProfile): Contract;
|
|
23
|
+
}
|
|
24
|
+
export interface IBesuGasEstimator {
|
|
25
|
+
estimateGas(profile: BesuRpcProfile, tx: TransactionRequest, gasLimitOverride?: bigint): Promise<bigint>;
|
|
26
|
+
}
|
|
27
|
+
export interface IBesuTransactionBuilder {
|
|
28
|
+
buildAnchorOrderTransaction(profile: BesuRpcProfile, order: PurchaseOrder, auditProof: string, gasLimit?: bigint): TransactionRequest;
|
|
29
|
+
buildAudienceViewTransaction(profile: BesuRpcProfile, view: SharedOrderView, gasLimit?: bigint): BesuPrivateTransactionRequest;
|
|
30
|
+
}
|
|
31
|
+
export interface IBesuTransactionSender {
|
|
32
|
+
sendTransaction(signer: NonceManager, tx: TransactionRequest): Promise<string>;
|
|
33
|
+
}
|
|
34
|
+
export interface IBesuHealthChecker {
|
|
35
|
+
checkHealth(profile: BesuRpcProfile): Promise<BesuHealthStatus>;
|
|
36
|
+
}
|
|
37
|
+
export interface BesuHealthStatus {
|
|
38
|
+
healthy: boolean;
|
|
39
|
+
blockNumber?: bigint;
|
|
40
|
+
chainId?: number;
|
|
41
|
+
latencyMs: number;
|
|
42
|
+
error?: string;
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=ports.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ports.d.ts","sourceRoot":"","sources":["../../../src/integrations/besu-client/ports.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,QAAQ,EACR,eAAe,EACf,YAAY,EACZ,kBAAkB,EAClB,MAAM,EACP,MAAM,QAAQ,CAAC;AAChB,OAAO,KAAK,EACV,aAAa,EACb,eAAe,EAChB,MAAM,kCAAkC,CAAC;AAE1C,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,eAAe,EAAE,MAAM,CAAC;IACxB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,6BAA6B;IAC5C,WAAW,EAAE,kBAAkB,CAAC;IAChC,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,mBAAmB;IAClC,oBAAoB,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,GAAG,cAAc,CAAC;IAC9D,aAAa,CAAC,OAAO,EAAE,cAAc,GAAG,cAAc,CAAC;CACxD;AAED,MAAM,WAAW,oBAAoB;IACnC,cAAc,CAAC,OAAO,EAAE,cAAc,GAAG,eAAe,CAAC;IACzD,YAAY,CAAC,OAAO,EAAE,cAAc,GAAG,MAAM,CAAC;IAC9C,mBAAmB,CAAC,OAAO,EAAE,cAAc,GAAG,YAAY,CAAC;IAC3D,cAAc,CAAC,OAAO,EAAE,cAAc,GAAG,QAAQ,CAAC;CACnD;AAED,MAAM,WAAW,iBAAiB;IAChC,WAAW,CACT,OAAO,EAAE,cAAc,EACvB,EAAE,EAAE,kBAAkB,EACtB,gBAAgB,CAAC,EAAE,MAAM,GACxB,OAAO,CAAC,MAAM,CAAC,CAAC;CACpB;AAED,MAAM,WAAW,uBAAuB;IACtC,2BAA2B,CACzB,OAAO,EAAE,cAAc,EACvB,KAAK,EAAE,aAAa,EACpB,UAAU,EAAE,MAAM,EAClB,QAAQ,CAAC,EAAE,MAAM,GAChB,kBAAkB,CAAC;IAEtB,4BAA4B,CAC1B,OAAO,EAAE,cAAc,EACvB,IAAI,EAAE,eAAe,EACrB,QAAQ,CAAC,EAAE,MAAM,GAChB,6BAA6B,CAAC;CAClC;AAED,MAAM,WAAW,sBAAsB;IACrC,eAAe,CACb,MAAM,EAAE,YAAY,EACpB,EAAE,EAAE,kBAAkB,GACrB,OAAO,CAAC,MAAM,CAAC,CAAC;CACpB;AAED,MAAM,WAAW,kBAAkB;IACjC,WAAW,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC;CACjE;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { type CircuitBreakerOptions } from "../shared/retry.js";
|
|
2
|
+
import type { CordaGatewayProfile, CordaGatewayRequest, ICordaFlowInvoker, ICordaProfileFactory, ICordaRequestBuilder, ProviderClearancePayload } from "./ports.js";
|
|
3
|
+
export type { CordaGatewayProfile, CordaGatewayRequest, ProviderClearancePayload, } from "./ports.js";
|
|
4
|
+
export declare class CordaProfileFactory implements ICordaProfileFactory {
|
|
5
|
+
createProfileFromEnv(env?: NodeJS.ProcessEnv): CordaGatewayProfile;
|
|
6
|
+
createProfile(profile: CordaGatewayProfile): CordaGatewayProfile;
|
|
7
|
+
}
|
|
8
|
+
export declare class CordaRequestBuilder implements ICordaRequestBuilder {
|
|
9
|
+
buildIssueClearanceRequest(profile: CordaGatewayProfile, payload: ProviderClearancePayload): CordaGatewayRequest;
|
|
10
|
+
}
|
|
11
|
+
export declare class CordaFlowInvoker implements ICordaFlowInvoker {
|
|
12
|
+
invokeFlow(request: CordaGatewayRequest): Promise<Response>;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Resilient Corda gateway client with circuit breaker and retry support.
|
|
16
|
+
*
|
|
17
|
+
* Circuit breaker prevents cascading failures when Corda REST API is unavailable.
|
|
18
|
+
* Retry policy handles transient HTTP errors (502, 503, 504, TIMEOUT).
|
|
19
|
+
*
|
|
20
|
+
* NOTE: sketch only — use a secrets manager or token provider in production
|
|
21
|
+
*/
|
|
22
|
+
export declare class CordaGatewayClientSketch implements ICordaProfileFactory, ICordaRequestBuilder, ICordaFlowInvoker {
|
|
23
|
+
private readonly profileFactory;
|
|
24
|
+
private readonly requestBuilder;
|
|
25
|
+
private readonly flowInvoker;
|
|
26
|
+
private readonly circuitBreaker;
|
|
27
|
+
constructor(circuitBreakerOptions?: Partial<CircuitBreakerOptions>);
|
|
28
|
+
createProfileFromEnv(env?: NodeJS.ProcessEnv): CordaGatewayProfile;
|
|
29
|
+
createProfile(profile: CordaGatewayProfile): CordaGatewayProfile;
|
|
30
|
+
buildIssueClearanceRequest(profile: CordaGatewayProfile, payload: ProviderClearancePayload): CordaGatewayRequest;
|
|
31
|
+
invokeFlow(request: CordaGatewayRequest): Promise<Response>;
|
|
32
|
+
/** Get circuit breaker state for monitoring dashboards. */
|
|
33
|
+
getCircuitBreakerHealth(): import("../shared/retry.js").CircuitBreakerHealth;
|
|
34
|
+
/** Reset circuit breaker (use after resolving underlying issues). */
|
|
35
|
+
resetCircuitBreaker(): void;
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/integrations/corda-gateway/index.ts"],"names":[],"mappings":"AACA,OAAO,EAKL,KAAK,qBAAqB,EAC3B,MAAM,oBAAoB,CAAC;AAM5B,OAAO,KAAK,EACV,mBAAmB,EACnB,mBAAmB,EACnB,iBAAiB,EACjB,oBAAoB,EACpB,oBAAoB,EACpB,wBAAwB,EACzB,MAAM,YAAY,CAAC;AAIpB,YAAY,EACV,mBAAmB,EACnB,mBAAmB,EACnB,wBAAwB,GACzB,MAAM,YAAY,CAAC;AAEpB,qBAAa,mBAAoB,YAAW,oBAAoB;IAC9D,oBAAoB,CAClB,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,mBAAmB;IAStB,aAAa,CAAC,OAAO,EAAE,mBAAmB,GAAG,mBAAmB;CAGjE;AAED,qBAAa,mBAAoB,YAAW,oBAAoB;IAC9D,0BAA0B,CACxB,OAAO,EAAE,mBAAmB,EAC5B,OAAO,EAAE,wBAAwB,GAChC,mBAAmB;CAgBvB;AAmID,qBAAa,gBAAiB,YAAW,iBAAiB;IAClD,UAAU,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,QAAQ,CAAC;CAkClE;AAED;;;;;;;GAOG;AACH,qBAAa,wBACX,YAAW,oBAAoB,EAAE,oBAAoB,EAAE,iBAAiB;IAExE,OAAO,CAAC,QAAQ,CAAC,cAAc,CAA6B;IAC5D,OAAO,CAAC,QAAQ,CAAC,cAAc,CAA6B;IAC5D,OAAO,CAAC,QAAQ,CAAC,WAAW,CAA0B;IACtD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAiB;gBAEpC,qBAAqB,CAAC,EAAE,OAAO,CAAC,qBAAqB,CAAC;IAOlE,oBAAoB,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,GAAG,mBAAmB;IAIlE,aAAa,CAAC,OAAO,EAAE,mBAAmB,GAAG,mBAAmB;IAIhE,0BAA0B,CACxB,OAAO,EAAE,mBAAmB,EAC5B,OAAO,EAAE,wBAAwB,GAChC,mBAAmB;IAItB,UAAU,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,QAAQ,CAAC;IAY3D,2DAA2D;IAC3D,uBAAuB;IAIvB,qEAAqE;IACrE,mBAAmB,IAAI,IAAI;CAG5B"}
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
import { getNumberEnv, getRequiredEnv } from "../shared/env.js";
|
|
2
|
+
import { CircuitBreaker, CORDA_RETRY_POLICY, CORDA_NON_RETRYABLE, withRetry, } from "../shared/retry.js";
|
|
3
|
+
import { createTracer, withSpan, TelemetryAttributes, } from "../../shared/telemetry.js";
|
|
4
|
+
const tracer = createTracer("corda-gateway");
|
|
5
|
+
export class CordaProfileFactory {
|
|
6
|
+
createProfileFromEnv(env = process.env) {
|
|
7
|
+
return {
|
|
8
|
+
baseUrl: getRequiredEnv("CORDA_GATEWAY_BASE_URL", env),
|
|
9
|
+
network: getRequiredEnv("CORDA_GATEWAY_NETWORK", env),
|
|
10
|
+
bearerToken: getRequiredEnv("CORDA_GATEWAY_TOKEN", env),
|
|
11
|
+
timeoutMs: getNumberEnv("CORDA_GATEWAY_TIMEOUT_MS", 10000, env),
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
createProfile(profile) {
|
|
15
|
+
return profile;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
export class CordaRequestBuilder {
|
|
19
|
+
buildIssueClearanceRequest(profile, payload) {
|
|
20
|
+
return {
|
|
21
|
+
method: "POST",
|
|
22
|
+
url: `${profile.baseUrl}/api/v1/networks/${profile.network}/flows/IssueProviderClearanceFlow`,
|
|
23
|
+
headers: {
|
|
24
|
+
"content-type": "application/json",
|
|
25
|
+
authorization: `Bearer ${profile.bearerToken}`,
|
|
26
|
+
},
|
|
27
|
+
body: JSON.stringify({
|
|
28
|
+
clientRequestId: `${payload.providerId}-${payload.scheduledAt}`,
|
|
29
|
+
command: payload.approved ? "ApproveClearance" : "RejectClearance",
|
|
30
|
+
payload,
|
|
31
|
+
}),
|
|
32
|
+
timeoutMs: profile.timeoutMs,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
import { lookup } from "node:dns/promises";
|
|
37
|
+
/**
|
|
38
|
+
* Check if an IP address is in a private/reserved range.
|
|
39
|
+
* Covers IPv4 private ranges, loopback, link-local, and IPv6 equivalents.
|
|
40
|
+
*/
|
|
41
|
+
function isPrivateIP(ip) {
|
|
42
|
+
// IPv4 private/reserved patterns
|
|
43
|
+
const ipv4PrivatePatterns = [
|
|
44
|
+
/^127\./, // loopback
|
|
45
|
+
/^10\./, // Class A private
|
|
46
|
+
/^172\.(1[6-9]|2\d|3[01])\./, // Class B private
|
|
47
|
+
/^192\.168\./, // Class C private
|
|
48
|
+
/^169\.254\./, // link-local
|
|
49
|
+
/^0\./, // current network
|
|
50
|
+
/^100\.(6[4-9]|[7-9]\d|1[01]\d|12[0-7])\./, // carrier-grade NAT
|
|
51
|
+
/^192\.0\.0\./, // IETF protocol assignments
|
|
52
|
+
/^192\.0\.2\./, // TEST-NET-1
|
|
53
|
+
/^198\.51\.100\./, // TEST-NET-2
|
|
54
|
+
/^203\.0\.113\./, // TEST-NET-3
|
|
55
|
+
/^224\./, // multicast
|
|
56
|
+
/^240\./, // reserved
|
|
57
|
+
/^255\.255\.255\.255$/, // broadcast
|
|
58
|
+
];
|
|
59
|
+
// IPv6 private/reserved patterns
|
|
60
|
+
const ipv6PrivatePatterns = [
|
|
61
|
+
/^::1$/, // loopback
|
|
62
|
+
/^::$/, // unspecified
|
|
63
|
+
/^::ffff:127\./, // IPv4-mapped loopback
|
|
64
|
+
/^::ffff:10\./, // IPv4-mapped Class A
|
|
65
|
+
/^::ffff:172\.(1[6-9]|2\d|3[01])\./, // IPv4-mapped Class B
|
|
66
|
+
/^::ffff:192\.168\./, // IPv4-mapped Class C
|
|
67
|
+
/^fc/, // unique local (fc00::/7)
|
|
68
|
+
/^fd/, // unique local (fc00::/7)
|
|
69
|
+
/^fe80:/, // link-local
|
|
70
|
+
/^ff/, // multicast
|
|
71
|
+
];
|
|
72
|
+
const lowerIp = ip.toLowerCase();
|
|
73
|
+
for (const pattern of ipv4PrivatePatterns) {
|
|
74
|
+
if (pattern.test(lowerIp))
|
|
75
|
+
return true;
|
|
76
|
+
}
|
|
77
|
+
for (const pattern of ipv6PrivatePatterns) {
|
|
78
|
+
if (pattern.test(lowerIp))
|
|
79
|
+
return true;
|
|
80
|
+
}
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Validates that a URL is safe to fetch (SSRF protection).
|
|
85
|
+
* - Must be HTTPS protocol
|
|
86
|
+
* - Must not resolve to private/internal IP addresses (prevents DNS rebinding)
|
|
87
|
+
* - Uses explicit allowlist approach for gateway hosts in production
|
|
88
|
+
*
|
|
89
|
+
* IMPORTANT: This performs DNS resolution to prevent DNS rebinding attacks where
|
|
90
|
+
* an attacker-controlled DNS name initially resolves to a public IP but later
|
|
91
|
+
* resolves to a private IP (e.g., 127.0.0.1, 10.x.x.x, etc.)
|
|
92
|
+
*
|
|
93
|
+
* @throws Error if URL fails validation
|
|
94
|
+
*/
|
|
95
|
+
async function validateGatewayUrl(urlString) {
|
|
96
|
+
const url = new URL(urlString);
|
|
97
|
+
// Require HTTPS for production gateway connections
|
|
98
|
+
if (url.protocol !== "https:") {
|
|
99
|
+
throw new Error(`SSRF protection: Corda gateway URL must use HTTPS, got ${url.protocol}`);
|
|
100
|
+
}
|
|
101
|
+
const hostname = url.hostname.toLowerCase();
|
|
102
|
+
// Quick check: block obviously private hostnames before DNS lookup
|
|
103
|
+
if (hostname === "localhost") {
|
|
104
|
+
throw new Error(`SSRF protection: Corda gateway URL must not target private networks`);
|
|
105
|
+
}
|
|
106
|
+
// Resolve hostname to IP address(es) and check each one
|
|
107
|
+
// This prevents DNS rebinding attacks where a hostname initially resolves
|
|
108
|
+
// to a public IP but later resolves to a private IP
|
|
109
|
+
try {
|
|
110
|
+
// Resolve both IPv4 and IPv6 addresses
|
|
111
|
+
const results = await Promise.allSettled([
|
|
112
|
+
lookup(hostname, { family: 4 }),
|
|
113
|
+
lookup(hostname, { family: 6 }),
|
|
114
|
+
]);
|
|
115
|
+
// Collect all resolved addresses
|
|
116
|
+
const addresses = [];
|
|
117
|
+
for (const result of results) {
|
|
118
|
+
if (result.status === "fulfilled") {
|
|
119
|
+
addresses.push(result.value.address);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
// If no addresses resolved, the hostname is invalid
|
|
123
|
+
if (addresses.length === 0) {
|
|
124
|
+
throw new Error(`SSRF protection: Could not resolve hostname ${hostname}`);
|
|
125
|
+
}
|
|
126
|
+
// Check all resolved IPs against private ranges
|
|
127
|
+
for (const ip of addresses) {
|
|
128
|
+
if (isPrivateIP(ip)) {
|
|
129
|
+
throw new Error(`SSRF protection: Corda gateway URL must not target private networks (resolved to ${ip})`);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
catch (err) {
|
|
134
|
+
if (err instanceof Error && err.message.startsWith("SSRF protection:")) {
|
|
135
|
+
throw err;
|
|
136
|
+
}
|
|
137
|
+
throw new Error(`SSRF protection: DNS resolution failed for ${hostname}: ${err instanceof Error ? err.message : String(err)}`, { cause: err });
|
|
138
|
+
}
|
|
139
|
+
return url;
|
|
140
|
+
}
|
|
141
|
+
export class CordaFlowInvoker {
|
|
142
|
+
async invokeFlow(request) {
|
|
143
|
+
return withSpan(tracer, "corda.invokeFlow", async (span) => {
|
|
144
|
+
span.setAttribute(TelemetryAttributes.BLOCKCHAIN_PLATFORM, "corda");
|
|
145
|
+
span.setAttribute("corda.method", request.method);
|
|
146
|
+
span.setAttribute("corda.timeout_ms", request.timeoutMs);
|
|
147
|
+
// Validate URL before making the request (SSRF protection)
|
|
148
|
+
// This performs DNS resolution to prevent DNS rebinding attacks
|
|
149
|
+
const validatedUrl = await validateGatewayUrl(request.url);
|
|
150
|
+
try {
|
|
151
|
+
const response = await fetch(validatedUrl.toString(), {
|
|
152
|
+
method: request.method,
|
|
153
|
+
headers: request.headers,
|
|
154
|
+
body: request.body,
|
|
155
|
+
signal: AbortSignal.timeout(request.timeoutMs),
|
|
156
|
+
});
|
|
157
|
+
span.setAttribute("corda.response_status", response.status);
|
|
158
|
+
if (!response.ok) {
|
|
159
|
+
const errorMsg = `Corda gateway error: ${response.status} ${response.statusText}`;
|
|
160
|
+
span.setAttribute(TelemetryAttributes.ERROR_MESSAGE, errorMsg);
|
|
161
|
+
throw new Error(errorMsg);
|
|
162
|
+
}
|
|
163
|
+
return response;
|
|
164
|
+
}
|
|
165
|
+
catch (err) {
|
|
166
|
+
if (err instanceof Error) {
|
|
167
|
+
span.setAttribute(TelemetryAttributes.ERROR_MESSAGE, err.message);
|
|
168
|
+
}
|
|
169
|
+
throw err;
|
|
170
|
+
}
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Resilient Corda gateway client with circuit breaker and retry support.
|
|
176
|
+
*
|
|
177
|
+
* Circuit breaker prevents cascading failures when Corda REST API is unavailable.
|
|
178
|
+
* Retry policy handles transient HTTP errors (502, 503, 504, TIMEOUT).
|
|
179
|
+
*
|
|
180
|
+
* NOTE: sketch only — use a secrets manager or token provider in production
|
|
181
|
+
*/
|
|
182
|
+
export class CordaGatewayClientSketch {
|
|
183
|
+
profileFactory = new CordaProfileFactory();
|
|
184
|
+
requestBuilder = new CordaRequestBuilder();
|
|
185
|
+
flowInvoker = new CordaFlowInvoker();
|
|
186
|
+
circuitBreaker;
|
|
187
|
+
constructor(circuitBreakerOptions) {
|
|
188
|
+
this.circuitBreaker = new CircuitBreaker(circuitBreakerOptions, "corda-gateway");
|
|
189
|
+
}
|
|
190
|
+
createProfileFromEnv(env) {
|
|
191
|
+
return this.profileFactory.createProfileFromEnv(env);
|
|
192
|
+
}
|
|
193
|
+
createProfile(profile) {
|
|
194
|
+
return this.profileFactory.createProfile(profile);
|
|
195
|
+
}
|
|
196
|
+
buildIssueClearanceRequest(profile, payload) {
|
|
197
|
+
return this.requestBuilder.buildIssueClearanceRequest(profile, payload);
|
|
198
|
+
}
|
|
199
|
+
invokeFlow(request) {
|
|
200
|
+
return this.circuitBreaker.execute(() => withRetry(() => this.flowInvoker.invokeFlow(request), CORDA_RETRY_POLICY, CORDA_NON_RETRYABLE, extractHttpErrorCode, "corda.invokeFlow"));
|
|
201
|
+
}
|
|
202
|
+
/** Get circuit breaker state for monitoring dashboards. */
|
|
203
|
+
getCircuitBreakerHealth() {
|
|
204
|
+
return this.circuitBreaker.getHealthStatus();
|
|
205
|
+
}
|
|
206
|
+
/** Reset circuit breaker (use after resolving underlying issues). */
|
|
207
|
+
resetCircuitBreaker() {
|
|
208
|
+
this.circuitBreaker.reset();
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Extract HTTP error codes for retry policy decisions.
|
|
213
|
+
*/
|
|
214
|
+
function extractHttpErrorCode(err) {
|
|
215
|
+
if (err instanceof Error) {
|
|
216
|
+
// Check for timeout errors
|
|
217
|
+
if (err.name === "TimeoutError" || err.message.includes("timeout")) {
|
|
218
|
+
return "TIMEOUT";
|
|
219
|
+
}
|
|
220
|
+
// Extract HTTP status from error message (e.g., "Corda gateway error: 502 Bad Gateway")
|
|
221
|
+
const statusMatch = err.message.match(/(\d{3})/);
|
|
222
|
+
if (statusMatch?.[1]) {
|
|
223
|
+
return statusMatch[1];
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
if (err && typeof err === "object") {
|
|
227
|
+
const e = err;
|
|
228
|
+
if (typeof e.status === "number")
|
|
229
|
+
return String(e.status);
|
|
230
|
+
if (typeof e.statusCode === "number")
|
|
231
|
+
return String(e.statusCode);
|
|
232
|
+
}
|
|
233
|
+
return "UNKNOWN";
|
|
234
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export interface CordaGatewayProfile {
|
|
2
|
+
baseUrl: string;
|
|
3
|
+
network: string;
|
|
4
|
+
bearerToken: string;
|
|
5
|
+
timeoutMs: number;
|
|
6
|
+
}
|
|
7
|
+
export interface CordaGatewayRequest {
|
|
8
|
+
method: "POST";
|
|
9
|
+
url: string;
|
|
10
|
+
headers: Record<string, string>;
|
|
11
|
+
body: string;
|
|
12
|
+
timeoutMs: number;
|
|
13
|
+
}
|
|
14
|
+
export interface ProviderClearancePayload {
|
|
15
|
+
providerId: string;
|
|
16
|
+
facility: string;
|
|
17
|
+
jurisdiction: string;
|
|
18
|
+
scheduledAt: string;
|
|
19
|
+
requiredCredentials: string[];
|
|
20
|
+
approved: boolean;
|
|
21
|
+
reasons: string[];
|
|
22
|
+
}
|
|
23
|
+
export interface ICordaProfileFactory {
|
|
24
|
+
createProfileFromEnv(env?: NodeJS.ProcessEnv): CordaGatewayProfile;
|
|
25
|
+
createProfile(profile: CordaGatewayProfile): CordaGatewayProfile;
|
|
26
|
+
}
|
|
27
|
+
export interface ICordaRequestBuilder {
|
|
28
|
+
buildIssueClearanceRequest(profile: CordaGatewayProfile, payload: ProviderClearancePayload): CordaGatewayRequest;
|
|
29
|
+
}
|
|
30
|
+
export interface ICordaFlowInvoker {
|
|
31
|
+
invokeFlow(request: CordaGatewayRequest): Promise<Response>;
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=ports.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ports.d.ts","sourceRoot":"","sources":["../../../src/integrations/corda-gateway/ports.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,wBAAwB;IACvC,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,mBAAmB,EAAE,MAAM,EAAE,CAAC;IAC9B,QAAQ,EAAE,OAAO,CAAC;IAClB,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,oBAAoB;IACnC,oBAAoB,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,GAAG,mBAAmB,CAAC;IACnE,aAAa,CAAC,OAAO,EAAE,mBAAmB,GAAG,mBAAmB,CAAC;CAClE;AAED,MAAM,WAAW,oBAAoB;IACnC,0BAA0B,CACxB,OAAO,EAAE,mBAAmB,EAC5B,OAAO,EAAE,wBAAwB,GAChC,mBAAmB,CAAC;CACxB;AAED,MAAM,WAAW,iBAAiB;IAChC,UAAU,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;CAC7D"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|