@distrohelena/canton-typescript-sdk 0.1.48 → 0.1.50
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/dist/cjs/core/auth/refreshing-bearer-token-auth-provider.js +28 -0
- package/dist/cjs/core/errors/grpc-transport-error.js +137 -4
- package/dist/cjs/index.js +8 -6
- package/dist/core/auth/refreshing-bearer-token-auth-provider.d.ts +13 -0
- package/dist/core/auth/refreshing-bearer-token-auth-provider.js +24 -0
- package/dist/core/errors/grpc-transport-error.d.ts +7 -0
- package/dist/core/errors/grpc-transport-error.js +137 -4
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1 -0
- package/node/start-local.sh +36 -1
- package/package.json +3 -1
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.RefreshingBearerTokenAuthProvider = void 0;
|
|
4
|
+
const validation_error_js_1 = require("../errors/validation-error.js");
|
|
5
|
+
/**
|
|
6
|
+
* Bearer auth for tokens that rotate: the supplier runs on EVERY request, so long-lived processes — TTL
|
|
7
|
+
* cache re-warms, incremental history reads, timers — always present a current token instead of the one the
|
|
8
|
+
* process booted with. The supplier owns caching/refresh policy (e.g. reuse the token until shortly before
|
|
9
|
+
* its exp claim, then refetch); returning an empty value fails the request with a clear error rather than
|
|
10
|
+
* sending "Bearer " to the participant.
|
|
11
|
+
*/
|
|
12
|
+
class RefreshingBearerTokenAuthProvider {
|
|
13
|
+
tokenSupplier;
|
|
14
|
+
constructor(tokenSupplier) {
|
|
15
|
+
this.tokenSupplier = tokenSupplier;
|
|
16
|
+
if (typeof tokenSupplier !== "function") {
|
|
17
|
+
throw new validation_error_js_1.ValidationError("RefreshingBearerTokenAuthProvider requires a token supplier function.");
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
async getHeadersAsync() {
|
|
21
|
+
const token = await this.tokenSupplier();
|
|
22
|
+
if (typeof token !== "string" || token.trim().length === 0) {
|
|
23
|
+
throw new validation_error_js_1.ValidationError("RefreshingBearerTokenAuthProvider token supplier returned an empty token.");
|
|
24
|
+
}
|
|
25
|
+
return { authorization: `Bearer ${token}` };
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
exports.RefreshingBearerTokenAuthProvider = RefreshingBearerTokenAuthProvider;
|
|
@@ -9,14 +9,16 @@ class GrpcTransportError extends transport_error_js_1.TransportError {
|
|
|
9
9
|
methodName;
|
|
10
10
|
metadata;
|
|
11
11
|
status;
|
|
12
|
+
errorInfo;
|
|
12
13
|
cause;
|
|
13
|
-
constructor(message, rawError, metadata, status) {
|
|
14
|
+
constructor(message, rawError, metadata, status, errorInfo) {
|
|
14
15
|
super(message);
|
|
15
16
|
this.grpcCode = rawError.code;
|
|
16
17
|
this.serviceName = rawError.serviceName;
|
|
17
18
|
this.methodName = rawError.methodName;
|
|
18
19
|
this.metadata = metadata;
|
|
19
20
|
this.status = status;
|
|
21
|
+
this.errorInfo = errorInfo;
|
|
20
22
|
this.cause = rawError;
|
|
21
23
|
}
|
|
22
24
|
static fromUnknown(error) {
|
|
@@ -25,7 +27,8 @@ class GrpcTransportError extends transport_error_js_1.TransportError {
|
|
|
25
27
|
}
|
|
26
28
|
const metadata = copyMetadata(error.meta);
|
|
27
29
|
const status = decodeStatusDetails(error.meta);
|
|
28
|
-
|
|
30
|
+
const errorInfo = decodeErrorInfo(status);
|
|
31
|
+
return new GrpcTransportError(formatMessage(error, status, errorInfo), error, metadata, status, errorInfo);
|
|
29
32
|
}
|
|
30
33
|
}
|
|
31
34
|
exports.GrpcTransportError = GrpcTransportError;
|
|
@@ -71,10 +74,140 @@ function toBinary(value) {
|
|
|
71
74
|
}
|
|
72
75
|
return value instanceof Uint8Array ? value : undefined;
|
|
73
76
|
}
|
|
74
|
-
|
|
77
|
+
/**
|
|
78
|
+
* Decodes the google.rpc.ErrorInfo entry from a status' packed details. The message type is small and
|
|
79
|
+
* stable (reason/domain/metadata), so it is read directly off the wire instead of adding the whole
|
|
80
|
+
* google.rpc.error_details surface to the generated bindings. Anything malformed yields undefined rather
|
|
81
|
+
* than masking the original RPC failure.
|
|
82
|
+
*/
|
|
83
|
+
function decodeErrorInfo(status) {
|
|
84
|
+
for (const detail of status?.details ?? []) {
|
|
85
|
+
if (typeof detail.typeUrl !== "string" || !detail.typeUrl.endsWith("/google.rpc.ErrorInfo") || !(detail.value instanceof Uint8Array)) {
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
const decoded = readErrorInfo(detail.value);
|
|
89
|
+
if (decoded !== undefined) {
|
|
90
|
+
return decoded;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
return undefined;
|
|
94
|
+
}
|
|
95
|
+
function readErrorInfo(bytes) {
|
|
96
|
+
try {
|
|
97
|
+
let reason = "";
|
|
98
|
+
let domain = "";
|
|
99
|
+
const metadata = {};
|
|
100
|
+
const reader = wireReader(bytes);
|
|
101
|
+
while (reader.remaining()) {
|
|
102
|
+
const tag = reader.varint();
|
|
103
|
+
const field = Math.floor(tag / 8);
|
|
104
|
+
const wireType = tag % 8;
|
|
105
|
+
if (field === 1 && wireType === 2) {
|
|
106
|
+
reason = reader.string();
|
|
107
|
+
}
|
|
108
|
+
else if (field === 2 && wireType === 2) {
|
|
109
|
+
domain = reader.string();
|
|
110
|
+
}
|
|
111
|
+
else if (field === 3 && wireType === 2) {
|
|
112
|
+
const entry = wireReader(reader.bytes());
|
|
113
|
+
let key = "";
|
|
114
|
+
let value = "";
|
|
115
|
+
while (entry.remaining()) {
|
|
116
|
+
const entryTag = entry.varint();
|
|
117
|
+
if (Math.floor(entryTag / 8) === 1 && entryTag % 8 === 2) {
|
|
118
|
+
key = entry.string();
|
|
119
|
+
}
|
|
120
|
+
else if (Math.floor(entryTag / 8) === 2 && entryTag % 8 === 2) {
|
|
121
|
+
value = entry.string();
|
|
122
|
+
}
|
|
123
|
+
else {
|
|
124
|
+
entry.skip(entryTag % 8);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
if (key.length > 0) {
|
|
128
|
+
metadata[key] = value;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
else {
|
|
132
|
+
reader.skip(wireType);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
return reason.length === 0 ? undefined : Object.freeze({ reason, domain, metadata: Object.freeze(metadata) });
|
|
136
|
+
}
|
|
137
|
+
catch {
|
|
138
|
+
return undefined;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
function wireReader(bytes) {
|
|
142
|
+
let offset = 0;
|
|
143
|
+
const varint = () => {
|
|
144
|
+
let result = 0;
|
|
145
|
+
let shift = 1;
|
|
146
|
+
for (let index = 0; index < 8; index += 1) {
|
|
147
|
+
const byte = bytes[offset];
|
|
148
|
+
if (byte === undefined) {
|
|
149
|
+
throw new Error("truncated varint");
|
|
150
|
+
}
|
|
151
|
+
offset += 1;
|
|
152
|
+
result += (byte & 0x7f) * shift;
|
|
153
|
+
if ((byte & 0x80) === 0) {
|
|
154
|
+
return result;
|
|
155
|
+
}
|
|
156
|
+
shift *= 128;
|
|
157
|
+
}
|
|
158
|
+
throw new Error("varint too long");
|
|
159
|
+
};
|
|
160
|
+
const rawBytes = () => {
|
|
161
|
+
const length = varint();
|
|
162
|
+
if (offset + length > bytes.length) {
|
|
163
|
+
throw new Error("truncated bytes");
|
|
164
|
+
}
|
|
165
|
+
const slice = bytes.subarray(offset, offset + length);
|
|
166
|
+
offset += length;
|
|
167
|
+
return slice;
|
|
168
|
+
};
|
|
169
|
+
return {
|
|
170
|
+
remaining: () => offset < bytes.length,
|
|
171
|
+
varint,
|
|
172
|
+
bytes: rawBytes,
|
|
173
|
+
string: () => new TextDecoder("utf-8", { fatal: true }).decode(rawBytes()),
|
|
174
|
+
skip: (wireType) => {
|
|
175
|
+
if (wireType === 0) {
|
|
176
|
+
varint();
|
|
177
|
+
}
|
|
178
|
+
else if (wireType === 1) {
|
|
179
|
+
offset += 8;
|
|
180
|
+
}
|
|
181
|
+
else if (wireType === 2) {
|
|
182
|
+
rawBytes();
|
|
183
|
+
}
|
|
184
|
+
else if (wireType === 5) {
|
|
185
|
+
offset += 4;
|
|
186
|
+
}
|
|
187
|
+
else {
|
|
188
|
+
throw new Error(`unsupported wire type ${wireType}`);
|
|
189
|
+
}
|
|
190
|
+
if (offset > bytes.length) {
|
|
191
|
+
throw new Error("truncated field");
|
|
192
|
+
}
|
|
193
|
+
},
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
function formatMessage(error, status, errorInfo) {
|
|
75
197
|
const operation = [error.serviceName, error.methodName]
|
|
76
198
|
.filter((part) => part !== undefined)
|
|
77
199
|
.join(".");
|
|
78
200
|
const location = operation.length > 0 ? ` from ${operation}` : "";
|
|
79
|
-
|
|
201
|
+
const parts = [];
|
|
202
|
+
// Participants often pair a generic transport message with the real explanation in the status trailer.
|
|
203
|
+
if (status !== undefined && status.message.length > 0 && status.message !== error.message) {
|
|
204
|
+
parts.push(`status: ${status.message}`);
|
|
205
|
+
}
|
|
206
|
+
if (errorInfo !== undefined) {
|
|
207
|
+
const metadataEntries = Object.entries(errorInfo.metadata);
|
|
208
|
+
parts.push(`reason: ${errorInfo.reason}`
|
|
209
|
+
+ (metadataEntries.length === 0 ? "" : ` (${metadataEntries.map(([key, value]) => `${key}=${value}`).join(", ")})`));
|
|
210
|
+
}
|
|
211
|
+
const suffix = parts.length === 0 ? "" : ` [${parts.join("; ")}]`;
|
|
212
|
+
return `gRPC ${error.code}${location}: ${error.message}${suffix}`;
|
|
80
213
|
}
|
package/dist/cjs/index.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
4
|
-
exports.
|
|
5
|
-
exports.
|
|
6
|
-
exports.
|
|
7
|
-
exports.
|
|
8
|
-
exports.EndpointNotConfiguredError = exports.ObjectDisposedError = exports.NotSupportedError = exports.ConflictError = exports.TimeoutError = exports.SigningError = exports.GrpcTransportError = exports.TransportError = exports.AuthorizationError = exports.AuthenticationError = exports.ActiveContractsTraversalError = exports.ValidationError = exports.CantonError = exports.SynchronizerTime = exports.ParticipantNodeStatus = exports.PartyDetails = exports.UploadDarFileResponse = exports.GrantUserRightsResponse = exports.SubmitCommandResponse = exports.TopologyListPartiesResponse = exports.TopologyListVettedPackagesResponse = exports.ListVettedPackagesResponse = exports.ListUsersResponse = exports.ListUserRightsResponse = exports.ListSynchronizerTrustCertificateResponse = exports.ListSynchronizerParametersStateResponse = exports.ListSequencingParametersStateResponse = exports.ListSequencerSynchronizerStateResponse = exports.ListPartyToParticipantResponse = exports.ListPartyToKeyMappingResponse = exports.ListPartyHostingLimitsResponse = exports.ListParticipantSynchronizerPermissionResponse = exports.ListKeyOwnersResponse = exports.ListKnownPartiesResponse = exports.ListKnownPackagesResponse = exports.ListIdentityProviderConfigsResponse = exports.ListDarsResponse = exports.ListPackagesResponse = exports.ListOwnerToKeyMappingResponse = exports.ListNamespaceDelegationResponse = exports.ListMediatorSynchronizerStateResponse = exports.ListLsuSequencerConnectionSuccessorResponse = exports.ListLsuAnnouncementResponse = exports.ListDecentralizedNamespaceDefinitionResponse = exports.ListAllResponse = exports.GetUserResponse = void 0;
|
|
3
|
+
exports.ExternalPartyCryptoKeyFormat = exports.TransportKind = exports.TransportCapability = exports.SignCommandResult = exports.SignCommandRequest = exports.RefreshingBearerTokenAuthProvider = exports.BearerTokenAuthProvider = exports.SynchronizerConnectivityServiceClient = exports.VersionServiceClient = exports.UserManagementServiceClient = exports.UpdateServiceClient = exports.TrafficControlServiceClient = exports.TopologyManagerWriteServiceClient = exports.TopologyManagerReadServiceClient = exports.TopologyAggregationServiceClient = exports.StateServiceClient = exports.ResourceManagementServiceClient = exports.PruningServiceClient = exports.PartyManagementServiceClient = exports.ParticipantStatusServiceClient = exports.ParticipantRepairServiceClient = exports.ParticipantPackageServiceClient = exports.ParticipantPartyManagementServiceClient = exports.ParticipantInspectionServiceClient = exports.PackageServiceClient = exports.PackageManagementServiceClient = exports.IdentityProviderConfigServiceClient = exports.IdentityInitializationServiceClient = exports.HealthServiceClient = exports.EventQueryServiceClient = exports.ContractServiceClient = exports.CommandSubmissionServiceClient = exports.CommandServiceClient = exports.CommandInspectionServiceClient = exports.CommandCompletionServiceClient = exports.ExternalPartyActivationResponse = exports.ExternalPartyActivationRequest = exports.ExternalPartyActivationClient = exports.CantonClientOptions = exports.CantonHashingClient = exports.PqsSchemaProfileError = exports.PqsQueryError = exports.QuerySnapshotIncompleteError = exports.QueryCapabilityError = exports.HistoryWalkRequiredError = exports.ContractCacheRequiredError = exports.MemoryQueryCache = exports.QuerySource = exports.CantonManager = exports.CantonClient = void 0;
|
|
4
|
+
exports.OperationDeadline = exports.RequestOptions = exports.ReceivedAcsCommitmentState = exports.ReceivedAcsCommitmentPerSynchronizer = exports.ReceivedAcsCommitment = exports.PruningSchedule = exports.ParticipantPruningSchedule = exports.PendingOperationMetadata = exports.PackageStatus = exports.CantonHashPurpose = exports.HashFunction = exports.PackageFormat = exports.OffsetCheckpoint = exports.ObjectMeta = exports.LedgerUser = exports.KnownPackageDetails = exports.IdentityProviderConfig = exports.UserRightKind = exports.EventStreamKind = exports.DamlParty = exports.DamlNumeric = exports.ContractCreated = exports.ContractArchived = exports.CounterParticipantInfo = exports.CommitmentTimeRange = exports.CommitmentInterval = exports.Completion = exports.CommandUpdateSummary = exports.CommandTiming = exports.CommandStatus = exports.CommandState = exports.CommandRequestStatistics = exports.CommandInspectionContract = exports.ConnectedSynchronizerStatus = exports.ConnectedSynchronizer = exports.ConnectedSynchronizerHealth = exports.AdminTopologyQueueStatus = exports.AdminNotInitializedStatus = exports.AdminNotInitializedExternalInputKind = exports.AdminNodeStatus = exports.AdminComponentStatus = exports.AdminComponentHealthKind = exports.SubmissionMode = exports.GrpcChannelSecurity = exports.ExternalPartySigningPublicKey = exports.ExternalPartySigningKeySpec = exports.ExternalPartySigningAlgorithmSpec = exports.ExternalPartySignatureFormat = exports.ExternalPartySignature = exports.ExternalPartyOnboardingTransaction = void 0;
|
|
5
|
+
exports.TopologyPartyParticipant = exports.TopologyMappingResult = exports.TopologyMappingOperation = exports.TopologyMappingCode = exports.TopologyKeyOwnerResult = exports.MultiTopologyTransactionSignature = exports.GeneratedTopologyTransaction = exports.TopologyEncryptionPublicKey = exports.ExternalTopologySignature = exports.TopologyDuration = exports.TopologyBaseResult = exports.TopologyBaseQuery = exports.SynchronizerTrustCertificate = exports.SequencerSynchronizerState = exports.PartyToParticipantParticipant = exports.PartyToParticipantOnboarding = exports.PartyToParticipant = exports.PartyToKeyMapping = exports.PartyHostingLimits = exports.ParticipantSynchronizerPermission = exports.ParticipantSynchronizerLimits = exports.ParticipantPermission = exports.OwnerToKeyMapping = exports.OnboardingRestriction = exports.NamespaceDelegationRestrictionKind = exports.NamespaceDelegationRestriction = exports.NamespaceDelegation = exports.MediatorSynchronizerState = exports.LsuSequencerConnectionSuccessor = exports.LsuSequencerConnection = exports.LsuAnnouncement = exports.DynamicSynchronizerParameters = exports.DynamicSequencingParameters = exports.DecentralizedNamespaceDefinition = exports.AcsCommitmentsCatchUpConfig = exports.WaitCommitmentsSetup = exports.TopologyStateFilter = exports.SynchronizerTimeRange = exports.SlowCounterParticipantSynchronizerConfig = exports.SentAcsCommitmentState = exports.SentAcsCommitmentPerSynchronizer = exports.SentAcsCommitment = exports.SdkCommand = exports.SafeToPruneCommitmentState = exports.ParticipantPackageDescription = exports.ParticipantModuleDescription = exports.ParticipantDarDescription = exports.PackageReference = exports.PackageMetadataFilter = exports.ActiveContractsTraversalOptions = void 0;
|
|
6
|
+
exports.GetActiveContractsRequest = exports.GetActiveContractsPageRequest = exports.GetDarRequest = exports.GetDarContentsRequest = exports.AssembleSignedTopologyTransactionsRequest = exports.SubmitCommandTransactionResponse = exports.DamlRecord = exports.DamlEnum = exports.DamlVariant = exports.DamlGenMap = exports.DamlTextMap = exports.DamlTimestamp = exports.DamlDate = exports.DamlUnit = exports.DamlContractId = exports.PreparedCommandSubmission = exports.DisclosedContract = exports.AllocatePartyRequest = exports.CreateExternalPartyRequest = exports.PreparedDecentralizedParty = exports.FinalizeDecentralizedPartyRequest = exports.CreateDecentralizedPartyRequest = exports.ExerciseCommand = exports.ExerciseByKeyCommand = exports.CreateCommand = exports.CreateAndExerciseCommand = exports.SignedTopologyTransaction = exports.PreparedTopologyTransaction = exports.VettedPackages = exports.VettedPackage = exports.TrafficControlParameters = exports.TopologyVettedPackages = exports.TopologyVettedPackage = exports.TopologyTransactions = exports.TopologyTransactionItem = exports.TopologyTransactionSignature = exports.TopologyTimeRange = exports.TopologyStoreTemporary = exports.TopologyStoreSynchronizer = exports.TopologyStoreKind = exports.TopologyStoreId = exports.TopologyStoreAuthorized = exports.TopologySigningPublicKey = exports.TopologySigningKeysWithThreshold = exports.TopologySignatureFormat = exports.TopologySignatureDelegation = exports.TopologyForceFlag = exports.TopologyPublicKey = exports.TopologyPartyResult = exports.TopologyPartyParticipantSynchronizerPermission = void 0;
|
|
7
|
+
exports.GetPackageStatusResponse = exports.GetPackageResponse = exports.GetLedgerEndResponse = exports.GetLatestPrunedOffsetsResponse = exports.GetIdentityProviderConfigResponse = exports.GetCommandStatusResponse = exports.GetConnectedSynchronizersResponse = exports.GetActiveContractsPageResponse = exports.GetDarResponse = exports.GetDarContentsResponse = exports.AllocatePartyResponse = exports.UploadDarFileRequest = exports.GrantUserRightsRequest = exports.WaitForPartyHostingRequest = exports.TopologyListPartiesRequest = exports.SubmitCommandsRequest = exports.ListUsersRequest = exports.ListUserRightsRequest = exports.ListKeyOwnersRequest = exports.ListIdentityProviderConfigsRequest = exports.ListDarsRequest = exports.ListKnownPackagesRequest = exports.ListKnownPartiesRequest = exports.TopologyListVettedPackagesRequest = exports.ListSynchronizerTrustCertificateRequest = exports.ListSynchronizerParametersStateRequest = exports.ListSequencingParametersStateRequest = exports.ListSequencerSynchronizerStateRequest = exports.ListPartyToParticipantRequest = exports.ListPartyToKeyMappingRequest = exports.ListVettedPackagesRequest = exports.ListPartyHostingLimitsRequest = exports.ListParticipantSynchronizerPermissionRequest = exports.ListOwnerToKeyMappingRequest = exports.ListNamespaceDelegationRequest = exports.ListMediatorSynchronizerStateRequest = exports.ListLsuSequencerConnectionSuccessorRequest = exports.ListLsuAnnouncementRequest = exports.GetUserRequest = exports.GetPartiesRequest = exports.GetLedgerEndRequest = exports.GetLatestPrunedOffsetsRequest = exports.GetConnectedSynchronizersRequest = exports.GetPackageStatusRequest = exports.GetPackageRequest = exports.GetIdentityProviderConfigRequest = exports.ListDecentralizedNamespaceDefinitionRequest = exports.ListAllRequest = exports.ListPackagesRequest = exports.GetCommandStatusRequest = void 0;
|
|
8
|
+
exports.EndpointNotConfiguredError = exports.ObjectDisposedError = exports.NotSupportedError = exports.ConflictError = exports.TimeoutError = exports.SigningError = exports.GrpcTransportError = exports.TransportError = exports.AuthorizationError = exports.AuthenticationError = exports.ActiveContractsTraversalError = exports.ValidationError = exports.CantonError = exports.SynchronizerTime = exports.ParticipantNodeStatus = exports.PartyDetails = exports.UploadDarFileResponse = exports.GrantUserRightsResponse = exports.SubmitCommandResponse = exports.TopologyListPartiesResponse = exports.TopologyListVettedPackagesResponse = exports.ListVettedPackagesResponse = exports.ListUsersResponse = exports.ListUserRightsResponse = exports.ListSynchronizerTrustCertificateResponse = exports.ListSynchronizerParametersStateResponse = exports.ListSequencingParametersStateResponse = exports.ListSequencerSynchronizerStateResponse = exports.ListPartyToParticipantResponse = exports.ListPartyToKeyMappingResponse = exports.ListPartyHostingLimitsResponse = exports.ListParticipantSynchronizerPermissionResponse = exports.ListKeyOwnersResponse = exports.ListKnownPartiesResponse = exports.ListKnownPackagesResponse = exports.ListIdentityProviderConfigsResponse = exports.ListDarsResponse = exports.ListPackagesResponse = exports.ListOwnerToKeyMappingResponse = exports.ListNamespaceDelegationResponse = exports.ListMediatorSynchronizerStateResponse = exports.ListLsuSequencerConnectionSuccessorResponse = exports.ListLsuAnnouncementResponse = exports.ListDecentralizedNamespaceDefinitionResponse = exports.ListAllResponse = exports.GetUserResponse = exports.GetPartiesResponse = void 0;
|
|
9
9
|
var canton_client_js_1 = require("./client/canton-client.js");
|
|
10
10
|
Object.defineProperty(exports, "CantonClient", { enumerable: true, get: function () { return canton_client_js_1.CantonClient; } });
|
|
11
11
|
var canton_manager_js_1 = require("./query/canton-manager.js");
|
|
@@ -94,6 +94,8 @@ var synchronizer_connectivity_service_client_js_1 = require("./services/synchron
|
|
|
94
94
|
Object.defineProperty(exports, "SynchronizerConnectivityServiceClient", { enumerable: true, get: function () { return synchronizer_connectivity_service_client_js_1.SynchronizerConnectivityServiceClient; } });
|
|
95
95
|
var bearer_token_auth_provider_js_1 = require("./core/auth/bearer-token-auth-provider.js");
|
|
96
96
|
Object.defineProperty(exports, "BearerTokenAuthProvider", { enumerable: true, get: function () { return bearer_token_auth_provider_js_1.BearerTokenAuthProvider; } });
|
|
97
|
+
var refreshing_bearer_token_auth_provider_js_1 = require("./core/auth/refreshing-bearer-token-auth-provider.js");
|
|
98
|
+
Object.defineProperty(exports, "RefreshingBearerTokenAuthProvider", { enumerable: true, get: function () { return refreshing_bearer_token_auth_provider_js_1.RefreshingBearerTokenAuthProvider; } });
|
|
97
99
|
var sign_command_request_js_1 = require("./core/signing/sign-command-request.js");
|
|
98
100
|
Object.defineProperty(exports, "SignCommandRequest", { enumerable: true, get: function () { return sign_command_request_js_1.SignCommandRequest; } });
|
|
99
101
|
var sign_command_result_js_1 = require("./core/signing/sign-command-result.js");
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { IAuthProvider } from "./auth-provider.interface.js";
|
|
2
|
+
/**
|
|
3
|
+
* Bearer auth for tokens that rotate: the supplier runs on EVERY request, so long-lived processes — TTL
|
|
4
|
+
* cache re-warms, incremental history reads, timers — always present a current token instead of the one the
|
|
5
|
+
* process booted with. The supplier owns caching/refresh policy (e.g. reuse the token until shortly before
|
|
6
|
+
* its exp claim, then refetch); returning an empty value fails the request with a clear error rather than
|
|
7
|
+
* sending "Bearer " to the participant.
|
|
8
|
+
*/
|
|
9
|
+
export declare class RefreshingBearerTokenAuthProvider implements IAuthProvider {
|
|
10
|
+
private readonly tokenSupplier;
|
|
11
|
+
constructor(tokenSupplier: () => string | Promise<string>);
|
|
12
|
+
getHeadersAsync(): Promise<Record<string, string>>;
|
|
13
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { ValidationError } from "../errors/validation-error.js";
|
|
2
|
+
/**
|
|
3
|
+
* Bearer auth for tokens that rotate: the supplier runs on EVERY request, so long-lived processes — TTL
|
|
4
|
+
* cache re-warms, incremental history reads, timers — always present a current token instead of the one the
|
|
5
|
+
* process booted with. The supplier owns caching/refresh policy (e.g. reuse the token until shortly before
|
|
6
|
+
* its exp claim, then refetch); returning an empty value fails the request with a clear error rather than
|
|
7
|
+
* sending "Bearer " to the participant.
|
|
8
|
+
*/
|
|
9
|
+
export class RefreshingBearerTokenAuthProvider {
|
|
10
|
+
tokenSupplier;
|
|
11
|
+
constructor(tokenSupplier) {
|
|
12
|
+
this.tokenSupplier = tokenSupplier;
|
|
13
|
+
if (typeof tokenSupplier !== "function") {
|
|
14
|
+
throw new ValidationError("RefreshingBearerTokenAuthProvider requires a token supplier function.");
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
async getHeadersAsync() {
|
|
18
|
+
const token = await this.tokenSupplier();
|
|
19
|
+
if (typeof token !== "string" || token.trim().length === 0) {
|
|
20
|
+
throw new ValidationError("RefreshingBearerTokenAuthProvider token supplier returned an empty token.");
|
|
21
|
+
}
|
|
22
|
+
return { authorization: `Bearer ${token}` };
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import type { Status as GrpcStatusDetails } from "../../transports/grpc/generated/canton/google/rpc/status.js";
|
|
2
2
|
import { TransportError } from "./transport-error.js";
|
|
3
3
|
export type GrpcErrorMetadata = Readonly<Record<string, readonly string[]>>;
|
|
4
|
+
/** The decoded google.rpc.ErrorInfo detail: the machine-readable reason behind a gRPC failure. */
|
|
5
|
+
export interface GrpcErrorInfo {
|
|
6
|
+
readonly reason: string;
|
|
7
|
+
readonly domain: string;
|
|
8
|
+
readonly metadata: Readonly<Record<string, string>>;
|
|
9
|
+
}
|
|
4
10
|
export type { GrpcStatusDetails };
|
|
5
11
|
export declare class GrpcTransportError extends TransportError {
|
|
6
12
|
readonly grpcCode: string;
|
|
@@ -8,6 +14,7 @@ export declare class GrpcTransportError extends TransportError {
|
|
|
8
14
|
readonly methodName?: string;
|
|
9
15
|
readonly metadata: GrpcErrorMetadata;
|
|
10
16
|
readonly status?: GrpcStatusDetails;
|
|
17
|
+
readonly errorInfo?: GrpcErrorInfo;
|
|
11
18
|
readonly cause: Error;
|
|
12
19
|
private constructor();
|
|
13
20
|
static fromUnknown(error: unknown): GrpcTransportError | undefined;
|
|
@@ -6,14 +6,16 @@ export class GrpcTransportError extends TransportError {
|
|
|
6
6
|
methodName;
|
|
7
7
|
metadata;
|
|
8
8
|
status;
|
|
9
|
+
errorInfo;
|
|
9
10
|
cause;
|
|
10
|
-
constructor(message, rawError, metadata, status) {
|
|
11
|
+
constructor(message, rawError, metadata, status, errorInfo) {
|
|
11
12
|
super(message);
|
|
12
13
|
this.grpcCode = rawError.code;
|
|
13
14
|
this.serviceName = rawError.serviceName;
|
|
14
15
|
this.methodName = rawError.methodName;
|
|
15
16
|
this.metadata = metadata;
|
|
16
17
|
this.status = status;
|
|
18
|
+
this.errorInfo = errorInfo;
|
|
17
19
|
this.cause = rawError;
|
|
18
20
|
}
|
|
19
21
|
static fromUnknown(error) {
|
|
@@ -22,7 +24,8 @@ export class GrpcTransportError extends TransportError {
|
|
|
22
24
|
}
|
|
23
25
|
const metadata = copyMetadata(error.meta);
|
|
24
26
|
const status = decodeStatusDetails(error.meta);
|
|
25
|
-
|
|
27
|
+
const errorInfo = decodeErrorInfo(status);
|
|
28
|
+
return new GrpcTransportError(formatMessage(error, status, errorInfo), error, metadata, status, errorInfo);
|
|
26
29
|
}
|
|
27
30
|
}
|
|
28
31
|
function isRpcErrorLike(error) {
|
|
@@ -67,10 +70,140 @@ function toBinary(value) {
|
|
|
67
70
|
}
|
|
68
71
|
return value instanceof Uint8Array ? value : undefined;
|
|
69
72
|
}
|
|
70
|
-
|
|
73
|
+
/**
|
|
74
|
+
* Decodes the google.rpc.ErrorInfo entry from a status' packed details. The message type is small and
|
|
75
|
+
* stable (reason/domain/metadata), so it is read directly off the wire instead of adding the whole
|
|
76
|
+
* google.rpc.error_details surface to the generated bindings. Anything malformed yields undefined rather
|
|
77
|
+
* than masking the original RPC failure.
|
|
78
|
+
*/
|
|
79
|
+
function decodeErrorInfo(status) {
|
|
80
|
+
for (const detail of status?.details ?? []) {
|
|
81
|
+
if (typeof detail.typeUrl !== "string" || !detail.typeUrl.endsWith("/google.rpc.ErrorInfo") || !(detail.value instanceof Uint8Array)) {
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
const decoded = readErrorInfo(detail.value);
|
|
85
|
+
if (decoded !== undefined) {
|
|
86
|
+
return decoded;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return undefined;
|
|
90
|
+
}
|
|
91
|
+
function readErrorInfo(bytes) {
|
|
92
|
+
try {
|
|
93
|
+
let reason = "";
|
|
94
|
+
let domain = "";
|
|
95
|
+
const metadata = {};
|
|
96
|
+
const reader = wireReader(bytes);
|
|
97
|
+
while (reader.remaining()) {
|
|
98
|
+
const tag = reader.varint();
|
|
99
|
+
const field = Math.floor(tag / 8);
|
|
100
|
+
const wireType = tag % 8;
|
|
101
|
+
if (field === 1 && wireType === 2) {
|
|
102
|
+
reason = reader.string();
|
|
103
|
+
}
|
|
104
|
+
else if (field === 2 && wireType === 2) {
|
|
105
|
+
domain = reader.string();
|
|
106
|
+
}
|
|
107
|
+
else if (field === 3 && wireType === 2) {
|
|
108
|
+
const entry = wireReader(reader.bytes());
|
|
109
|
+
let key = "";
|
|
110
|
+
let value = "";
|
|
111
|
+
while (entry.remaining()) {
|
|
112
|
+
const entryTag = entry.varint();
|
|
113
|
+
if (Math.floor(entryTag / 8) === 1 && entryTag % 8 === 2) {
|
|
114
|
+
key = entry.string();
|
|
115
|
+
}
|
|
116
|
+
else if (Math.floor(entryTag / 8) === 2 && entryTag % 8 === 2) {
|
|
117
|
+
value = entry.string();
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
entry.skip(entryTag % 8);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
if (key.length > 0) {
|
|
124
|
+
metadata[key] = value;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
reader.skip(wireType);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
return reason.length === 0 ? undefined : Object.freeze({ reason, domain, metadata: Object.freeze(metadata) });
|
|
132
|
+
}
|
|
133
|
+
catch {
|
|
134
|
+
return undefined;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
function wireReader(bytes) {
|
|
138
|
+
let offset = 0;
|
|
139
|
+
const varint = () => {
|
|
140
|
+
let result = 0;
|
|
141
|
+
let shift = 1;
|
|
142
|
+
for (let index = 0; index < 8; index += 1) {
|
|
143
|
+
const byte = bytes[offset];
|
|
144
|
+
if (byte === undefined) {
|
|
145
|
+
throw new Error("truncated varint");
|
|
146
|
+
}
|
|
147
|
+
offset += 1;
|
|
148
|
+
result += (byte & 0x7f) * shift;
|
|
149
|
+
if ((byte & 0x80) === 0) {
|
|
150
|
+
return result;
|
|
151
|
+
}
|
|
152
|
+
shift *= 128;
|
|
153
|
+
}
|
|
154
|
+
throw new Error("varint too long");
|
|
155
|
+
};
|
|
156
|
+
const rawBytes = () => {
|
|
157
|
+
const length = varint();
|
|
158
|
+
if (offset + length > bytes.length) {
|
|
159
|
+
throw new Error("truncated bytes");
|
|
160
|
+
}
|
|
161
|
+
const slice = bytes.subarray(offset, offset + length);
|
|
162
|
+
offset += length;
|
|
163
|
+
return slice;
|
|
164
|
+
};
|
|
165
|
+
return {
|
|
166
|
+
remaining: () => offset < bytes.length,
|
|
167
|
+
varint,
|
|
168
|
+
bytes: rawBytes,
|
|
169
|
+
string: () => new TextDecoder("utf-8", { fatal: true }).decode(rawBytes()),
|
|
170
|
+
skip: (wireType) => {
|
|
171
|
+
if (wireType === 0) {
|
|
172
|
+
varint();
|
|
173
|
+
}
|
|
174
|
+
else if (wireType === 1) {
|
|
175
|
+
offset += 8;
|
|
176
|
+
}
|
|
177
|
+
else if (wireType === 2) {
|
|
178
|
+
rawBytes();
|
|
179
|
+
}
|
|
180
|
+
else if (wireType === 5) {
|
|
181
|
+
offset += 4;
|
|
182
|
+
}
|
|
183
|
+
else {
|
|
184
|
+
throw new Error(`unsupported wire type ${wireType}`);
|
|
185
|
+
}
|
|
186
|
+
if (offset > bytes.length) {
|
|
187
|
+
throw new Error("truncated field");
|
|
188
|
+
}
|
|
189
|
+
},
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
function formatMessage(error, status, errorInfo) {
|
|
71
193
|
const operation = [error.serviceName, error.methodName]
|
|
72
194
|
.filter((part) => part !== undefined)
|
|
73
195
|
.join(".");
|
|
74
196
|
const location = operation.length > 0 ? ` from ${operation}` : "";
|
|
75
|
-
|
|
197
|
+
const parts = [];
|
|
198
|
+
// Participants often pair a generic transport message with the real explanation in the status trailer.
|
|
199
|
+
if (status !== undefined && status.message.length > 0 && status.message !== error.message) {
|
|
200
|
+
parts.push(`status: ${status.message}`);
|
|
201
|
+
}
|
|
202
|
+
if (errorInfo !== undefined) {
|
|
203
|
+
const metadataEntries = Object.entries(errorInfo.metadata);
|
|
204
|
+
parts.push(`reason: ${errorInfo.reason}`
|
|
205
|
+
+ (metadataEntries.length === 0 ? "" : ` (${metadataEntries.map(([key, value]) => `${key}=${value}`).join(", ")})`));
|
|
206
|
+
}
|
|
207
|
+
const suffix = parts.length === 0 ? "" : ` [${parts.join("; ")}]`;
|
|
208
|
+
return `gRPC ${error.code}${location}: ${error.message}${suffix}`;
|
|
76
209
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -50,6 +50,7 @@ export { VersionServiceClient } from "./services/version/version-service-client.
|
|
|
50
50
|
export { SynchronizerConnectivityServiceClient } from "./services/synchronizer-connectivity/synchronizer-connectivity-service-client.js";
|
|
51
51
|
export type { IAuthProvider } from "./core/auth/auth-provider.interface.js";
|
|
52
52
|
export { BearerTokenAuthProvider } from "./core/auth/bearer-token-auth-provider.js";
|
|
53
|
+
export { RefreshingBearerTokenAuthProvider } from "./core/auth/refreshing-bearer-token-auth-provider.js";
|
|
53
54
|
export type { ICommandSigner } from "./core/signing/command-signer.interface.js";
|
|
54
55
|
export { SignCommandRequest } from "./core/signing/sign-command-request.js";
|
|
55
56
|
export { SignCommandResult } from "./core/signing/sign-command-result.js";
|
|
@@ -300,6 +301,7 @@ export { AuthenticationError } from "./core/errors/authentication-error.js";
|
|
|
300
301
|
export { AuthorizationError } from "./core/errors/authorization-error.js";
|
|
301
302
|
export { TransportError } from "./core/errors/transport-error.js";
|
|
302
303
|
export { GrpcTransportError } from "./core/errors/grpc-transport-error.js";
|
|
304
|
+
export type { GrpcErrorInfo } from "./core/errors/grpc-transport-error.js";
|
|
303
305
|
export type { GrpcErrorMetadata, GrpcStatusDetails, } from "./core/errors/grpc-transport-error.js";
|
|
304
306
|
export { SigningError } from "./core/errors/signing-error.js";
|
|
305
307
|
export { TimeoutError } from "./core/errors/timeout-error.js";
|
package/dist/index.js
CHANGED
|
@@ -42,6 +42,7 @@ export { UserManagementServiceClient } from "./services/user-management/user-man
|
|
|
42
42
|
export { VersionServiceClient } from "./services/version/version-service-client.js";
|
|
43
43
|
export { SynchronizerConnectivityServiceClient } from "./services/synchronizer-connectivity/synchronizer-connectivity-service-client.js";
|
|
44
44
|
export { BearerTokenAuthProvider } from "./core/auth/bearer-token-auth-provider.js";
|
|
45
|
+
export { RefreshingBearerTokenAuthProvider } from "./core/auth/refreshing-bearer-token-auth-provider.js";
|
|
45
46
|
export { SignCommandRequest } from "./core/signing/sign-command-request.js";
|
|
46
47
|
export { SignCommandResult } from "./core/signing/sign-command-result.js";
|
|
47
48
|
export { TransportCapability } from "./core/transports/transport-capability.js";
|
package/node/start-local.sh
CHANGED
|
@@ -929,7 +929,19 @@ prerequisite_services() {
|
|
|
929
929
|
printf '%s\n' "${services[@]}"
|
|
930
930
|
}
|
|
931
931
|
|
|
932
|
+
resolve_pqs_enabled() {
|
|
933
|
+
local value="${LOCALNET_PQS:-1}"
|
|
934
|
+
if [[ "$value" != "0" && "$value" != "1" ]]; then
|
|
935
|
+
echo "LOCALNET_PQS must be 0 or 1." >&2
|
|
936
|
+
return 1
|
|
937
|
+
fi
|
|
938
|
+
printf '%s\n' "$value"
|
|
939
|
+
}
|
|
940
|
+
|
|
932
941
|
dependent_services() {
|
|
942
|
+
if [[ "$(resolve_pqs_enabled)" == "0" ]]; then
|
|
943
|
+
return 0
|
|
944
|
+
fi
|
|
933
945
|
printf '%s\n' pqs-app-provider pqs-sv
|
|
934
946
|
}
|
|
935
947
|
|
|
@@ -1042,6 +1054,23 @@ wait_for_canton_health() {
|
|
|
1042
1054
|
wait_for_container_readiness canton canton_and_extras_are_ready "$extra_participants"
|
|
1043
1055
|
}
|
|
1044
1056
|
|
|
1057
|
+
container_is_healthy() {
|
|
1058
|
+
local _container="$1"
|
|
1059
|
+
local lifecycle_state="$2"
|
|
1060
|
+
local health_status="$3"
|
|
1061
|
+
[[ "$lifecycle_state" == "running" && "$health_status" == "healthy" ]]
|
|
1062
|
+
}
|
|
1063
|
+
|
|
1064
|
+
wait_for_onboarding_health() {
|
|
1065
|
+
local onboarding_container
|
|
1066
|
+
onboarding_container="$(docker ps -a --filter name=splice-onboarding --format '{{.Names}}' | head -n 1)"
|
|
1067
|
+
if [[ -z "$onboarding_container" ]]; then
|
|
1068
|
+
echo "Unable to resolve the splice-onboarding container for readiness." >&2
|
|
1069
|
+
return 1
|
|
1070
|
+
fi
|
|
1071
|
+
wait_for_container_readiness "$onboarding_container" container_is_healthy
|
|
1072
|
+
}
|
|
1073
|
+
|
|
1045
1074
|
provision_extra_pqs() {
|
|
1046
1075
|
local count="$1"
|
|
1047
1076
|
if (( count == 0 )); then
|
|
@@ -1235,7 +1264,13 @@ start_ledger_stack() {
|
|
|
1235
1264
|
# gating so its healthcheck can retry until those apps are ready; PQS still
|
|
1236
1265
|
# starts afterward and retains its onboarding health dependency.
|
|
1237
1266
|
start_splice_services compose_args
|
|
1238
|
-
|
|
1267
|
+
if (( ${#followup_services[@]} > 0 )); then
|
|
1268
|
+
docker_compose "${compose_args[@]}" up -d --no-recreate "${followup_services[@]}"
|
|
1269
|
+
else
|
|
1270
|
+
# Without PQS nothing carries a service_healthy dependency on splice-onboarding, so wait explicitly —
|
|
1271
|
+
# the participant is not usable until onboarding finishes.
|
|
1272
|
+
wait_for_onboarding_health
|
|
1273
|
+
fi
|
|
1239
1274
|
|
|
1240
1275
|
if (( extra_participants > 0 )); then
|
|
1241
1276
|
wait_for_container_readiness splice container_health_is_ready
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@distrohelena/canton-typescript-sdk",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.50",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -140,6 +140,8 @@
|
|
|
140
140
|
"test": "vitest run --exclude 'tests/live/**' --maxWorkers=1 --testTimeout=15000",
|
|
141
141
|
"test:property": "vitest run tests/property --maxWorkers=1 --testTimeout=15000",
|
|
142
142
|
"test:live": "vitest run --dir tests/live --maxWorkers=1 --testTimeout=15000",
|
|
143
|
+
"test:live:matrix": "node scripts/live-matrix.mjs",
|
|
144
|
+
"test:full": "npm run test && node scripts/live-matrix.mjs",
|
|
143
145
|
"test:live:fuzz": "vitest run tests/live/specs/live-stateful-fuzzing.test.ts --maxWorkers=1 --testTimeout=300000",
|
|
144
146
|
"test:unit": "vitest run tests/unit",
|
|
145
147
|
"verify:pack": "node ./scripts/verify-npm-pack.mjs"
|