@taquito/taquito 24.3.1-beta.1 → 25.0.0-rc.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 +1 -1
- package/dist/lib/constants.js +4 -1
- package/dist/lib/estimate/errors.js +11 -1
- package/dist/lib/estimate/rpc-estimate-provider.js +171 -10
- package/dist/lib/version.js +2 -2
- package/dist/taquito.es6.js +187 -14
- package/dist/taquito.es6.js.map +1 -1
- package/dist/taquito.min.js +1 -1
- package/dist/taquito.min.js.LICENSE.txt +0 -2
- package/dist/taquito.umd.js +187 -13
- package/dist/taquito.umd.js.map +1 -1
- package/dist/types/constants.d.ts +4 -1
- package/dist/types/estimate/errors.d.ts +5 -0
- package/dist/types/estimate/rpc-estimate-provider.d.ts +9 -0
- package/package.json +15 -15
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@ The `@taquito/taquito` package contains higher-level functionality that builds u
|
|
|
7
7
|
## CDN Bundle
|
|
8
8
|
|
|
9
9
|
```html
|
|
10
|
-
<script src="https://unpkg.com/@taquito/taquito@
|
|
10
|
+
<script src="https://unpkg.com/@taquito/taquito@25.0.0-rc.1/dist/taquito.min.js"
|
|
11
11
|
crossorigin="anonymous" integrity="sha384-IxvP0ECHi5oqLyz94wF85pU9+ktcsL1HHtA42MITxZsGbsUMEu/g+0Vkjj5vqiMR"></script>
|
|
12
12
|
```
|
|
13
13
|
|
package/dist/lib/constants.js
CHANGED
|
@@ -49,6 +49,7 @@ var Protocols;
|
|
|
49
49
|
Protocols["PsRiotuma"] = "PsRiotumaAMotcRoDWW1bysEhQy2n1M5fy8JgRp8jjRfHGmfeA7";
|
|
50
50
|
Protocols["PtSeouLou"] = "PtSeouLouXkxhg39oWzjxDWaCydNfR3RxCUrNe4Q9Ro8BTehcbh";
|
|
51
51
|
Protocols["PtTALLiNt"] = "PtTALLiNtPec7mE7yY4m3k26J8Qukef3E3ehzhfXgFZKGtDdAXu";
|
|
52
|
+
Protocols["PsUshuai9"] = "PsUshuai9QapM5TGj1JpuVGkdxz5GykdnEvS6Rh8SUVrARvZLCY";
|
|
52
53
|
Protocols["ProtoALpha"] = "ProtoALphaALphaALphaALphaALphaALphaALphaALphaDdp3zK";
|
|
53
54
|
})(Protocols || (exports.Protocols = Protocols = {}));
|
|
54
55
|
exports.protocols = {
|
|
@@ -72,7 +73,8 @@ exports.protocols = {
|
|
|
72
73
|
'022': [Protocols.PsRiotuma],
|
|
73
74
|
'023': [Protocols.PtSeouLou],
|
|
74
75
|
'024': [Protocols.PtTALLiNt],
|
|
75
|
-
'025': [Protocols.
|
|
76
|
+
'025': [Protocols.PsUshuai9],
|
|
77
|
+
'026': [Protocols.ProtoALpha],
|
|
76
78
|
};
|
|
77
79
|
var ChainIds;
|
|
78
80
|
(function (ChainIds) {
|
|
@@ -99,6 +101,7 @@ var ChainIds;
|
|
|
99
101
|
ChainIds["RIONET"] = "NetXPdgaoabtBth";
|
|
100
102
|
ChainIds["SEOULNET"] = "NetXd56aBs1aeW3";
|
|
101
103
|
ChainIds["TALLINNNET"] = "NetXe8DbhW9A1eS";
|
|
104
|
+
ChainIds["USHUAIANET"] = "NetXpX8WSZkAZZA";
|
|
102
105
|
})(ChainIds || (exports.ChainIds = ChainIds = {}));
|
|
103
106
|
const getRevealGasLimit = (address) => Math.round((getRevealGasLimitInternal(address) * 37) / 10);
|
|
104
107
|
exports.getRevealGasLimit = getRevealGasLimit;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.RevealEstimateError = void 0;
|
|
3
|
+
exports.BatchGasLimitExceededError = exports.RevealEstimateError = void 0;
|
|
4
4
|
const core_1 = require("@taquito/core");
|
|
5
5
|
/**
|
|
6
6
|
* @category Error
|
|
@@ -14,3 +14,13 @@ class RevealEstimateError extends core_1.TaquitoError {
|
|
|
14
14
|
}
|
|
15
15
|
}
|
|
16
16
|
exports.RevealEstimateError = RevealEstimateError;
|
|
17
|
+
class BatchGasLimitExceededError extends core_1.TaquitoError {
|
|
18
|
+
constructor(requiredGasLimit, hardGasLimitPerBlock) {
|
|
19
|
+
super();
|
|
20
|
+
this.requiredGasLimit = requiredGasLimit;
|
|
21
|
+
this.hardGasLimitPerBlock = hardGasLimitPerBlock;
|
|
22
|
+
this.name = 'BatchGasLimitExceededError';
|
|
23
|
+
this.message = `Batch gas estimation requires at least ${requiredGasLimit} gas, which exceeds the per-block limit of ${hardGasLimitPerBlock}. Split the batch into smaller operations.`;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
exports.BatchGasLimitExceededError = BatchGasLimitExceededError;
|
|
@@ -28,6 +28,7 @@ class RPCEstimateProvider extends provider_1.Provider {
|
|
|
28
28
|
this.REVEAL_LENGTH_TZ4 = 622; // injecting size tz4=620
|
|
29
29
|
this.MILLIGAS_BUFFER = 100 * 1000; // 100 buffer depends on operation kind
|
|
30
30
|
this.STORAGE_BUFFER = 20; // according to octez-client
|
|
31
|
+
this.UNKNOWN_GAS_LIMIT_PER_OPERATION = 1000;
|
|
31
32
|
this.prepare = new prepare_provider_1.PrepareProvider(this.context);
|
|
32
33
|
}
|
|
33
34
|
async getKeys() {
|
|
@@ -85,6 +86,129 @@ class RPCEstimateProvider extends provider_1.Provider {
|
|
|
85
86
|
};
|
|
86
87
|
}
|
|
87
88
|
}
|
|
89
|
+
hasOperationGasExhausted(errors) {
|
|
90
|
+
return errors.some((error) => error.id.endsWith('gas_exhausted.operation'));
|
|
91
|
+
}
|
|
92
|
+
getOperationResult(content) {
|
|
93
|
+
return content?.metadata?.operation_result;
|
|
94
|
+
}
|
|
95
|
+
getInternalOperationResults(content) {
|
|
96
|
+
const internalResults = content?.metadata?.internal_operation_results;
|
|
97
|
+
return Array.isArray(internalResults) ? internalResults : [];
|
|
98
|
+
}
|
|
99
|
+
operationResultHasGasExhausted(result) {
|
|
100
|
+
return Array.isArray(result?.errors)
|
|
101
|
+
? result.errors.some((error) => error.id?.endsWith('gas_exhausted.operation'))
|
|
102
|
+
: false;
|
|
103
|
+
}
|
|
104
|
+
findGasExhaustedContentIndex(contents) {
|
|
105
|
+
const directFailureIndex = contents.findIndex((content) => this.operationResultHasGasExhausted(this.getOperationResult(content)));
|
|
106
|
+
if (directFailureIndex !== -1) {
|
|
107
|
+
return directFailureIndex;
|
|
108
|
+
}
|
|
109
|
+
const internalFailureIndex = contents.findIndex((content) => this.getInternalOperationResults(content).some((internalResult) => this.operationResultHasGasExhausted(internalResult.result)));
|
|
110
|
+
if (internalFailureIndex !== -1) {
|
|
111
|
+
return internalFailureIndex;
|
|
112
|
+
}
|
|
113
|
+
const firstSkippedIndex = contents.findIndex((content) => this.getOperationResult(content)?.status === 'skipped');
|
|
114
|
+
return firstSkippedIndex > 0 ? firstSkippedIndex - 1 : -1;
|
|
115
|
+
}
|
|
116
|
+
getContentGasLimit(content) {
|
|
117
|
+
const gasLimit = Number(content?.gas_limit);
|
|
118
|
+
return Number.isFinite(gasLimit) && gasLimit >= 0 ? gasLimit : 0;
|
|
119
|
+
}
|
|
120
|
+
getMeasuredGasLimit(content, hardGasLimitPerOperation) {
|
|
121
|
+
const operationResults = (0, errors_1.flattenOperationResult)({ contents: [content] });
|
|
122
|
+
const consumedMilligas = operationResults.reduce((total, result) => total + (Number(result.consumed_milligas) || 0), 0);
|
|
123
|
+
if (consumedMilligas <= 0) {
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
const safetyGas = (0, types_1.isOpWithGasBuffer)(content) ? this.MILLIGAS_BUFFER / 1000 : 0;
|
|
127
|
+
return Math.min(Math.ceil(consumedMilligas / 1000) + safetyGas, hardGasLimitPerOperation);
|
|
128
|
+
}
|
|
129
|
+
rebalanceGasLimits(op, opResponse, preparedOperation, constants) {
|
|
130
|
+
const hardGasLimitPerOperation = Number(constants.hard_gas_limit_per_operation);
|
|
131
|
+
const hardGasLimitPerBlock = Number(constants.hard_gas_limit_per_block);
|
|
132
|
+
const patchableIndexes = preparedOperation.simulation?.gasLimitPatchableIndexes?.filter((index) => index >= 0 && index < opResponse.contents.length);
|
|
133
|
+
if (!Array.isArray(op.operation.contents) ||
|
|
134
|
+
!patchableIndexes?.length ||
|
|
135
|
+
!Number.isFinite(hardGasLimitPerOperation) ||
|
|
136
|
+
!Number.isFinite(hardGasLimitPerBlock)) {
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
const responseContents = opResponse.contents;
|
|
140
|
+
const starvedIndex = this.findGasExhaustedContentIndex(responseContents);
|
|
141
|
+
if (starvedIndex === -1 || !patchableIndexes.includes(starvedIndex)) {
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
const patchableIndexSet = new Set(patchableIndexes);
|
|
145
|
+
const contents = op.operation.contents.map((content) => ({
|
|
146
|
+
...content,
|
|
147
|
+
}));
|
|
148
|
+
const patchedGasLimits = new Map();
|
|
149
|
+
let fixedGasTotal = 0;
|
|
150
|
+
let measuredGasTotal = 0;
|
|
151
|
+
const unknownPatchableIndexes = [];
|
|
152
|
+
for (const [index, content] of responseContents.entries()) {
|
|
153
|
+
if (!patchableIndexSet.has(index)) {
|
|
154
|
+
fixedGasTotal += this.getContentGasLimit(contents[index]);
|
|
155
|
+
continue;
|
|
156
|
+
}
|
|
157
|
+
if (index === starvedIndex) {
|
|
158
|
+
continue;
|
|
159
|
+
}
|
|
160
|
+
const status = this.getOperationResult(content)?.status;
|
|
161
|
+
const measuredGasLimit = status === 'applied' || status === 'backtracked'
|
|
162
|
+
? this.getMeasuredGasLimit(content, hardGasLimitPerOperation)
|
|
163
|
+
: undefined;
|
|
164
|
+
if (typeof measuredGasLimit === 'number') {
|
|
165
|
+
patchedGasLimits.set(index, measuredGasLimit);
|
|
166
|
+
measuredGasTotal += measuredGasLimit;
|
|
167
|
+
}
|
|
168
|
+
else {
|
|
169
|
+
unknownPatchableIndexes.push(index);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
const requiredKnownGas = fixedGasTotal + measuredGasTotal;
|
|
173
|
+
if (requiredKnownGas > hardGasLimitPerBlock) {
|
|
174
|
+
throw new errors_2.BatchGasLimitExceededError(requiredKnownGas, hardGasLimitPerBlock);
|
|
175
|
+
}
|
|
176
|
+
const gasAvailableAfterKnown = hardGasLimitPerBlock - requiredKnownGas;
|
|
177
|
+
const minimumUnknownGas = unknownPatchableIndexes.length + 1;
|
|
178
|
+
if (gasAvailableAfterKnown < minimumUnknownGas) {
|
|
179
|
+
throw new errors_2.BatchGasLimitExceededError(requiredKnownGas + minimumUnknownGas, hardGasLimitPerBlock);
|
|
180
|
+
}
|
|
181
|
+
const unknownGasLimit = unknownPatchableIndexes.length > 0
|
|
182
|
+
? Math.min(this.UNKNOWN_GAS_LIMIT_PER_OPERATION, Math.floor((gasAvailableAfterKnown - 1) / unknownPatchableIndexes.length))
|
|
183
|
+
: 0;
|
|
184
|
+
const gasReservedForUnknown = unknownGasLimit * unknownPatchableIndexes.length;
|
|
185
|
+
const starvedGasLimit = Math.min(hardGasLimitPerOperation, gasAvailableAfterKnown - gasReservedForUnknown);
|
|
186
|
+
if (starvedGasLimit <= 0) {
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
patchedGasLimits.set(starvedIndex, starvedGasLimit);
|
|
190
|
+
for (const index of unknownPatchableIndexes) {
|
|
191
|
+
patchedGasLimits.set(index, unknownGasLimit);
|
|
192
|
+
}
|
|
193
|
+
let patched = false;
|
|
194
|
+
for (const [index, gasLimit] of patchedGasLimits.entries()) {
|
|
195
|
+
if (this.getContentGasLimit(contents[index]) === gasLimit) {
|
|
196
|
+
continue;
|
|
197
|
+
}
|
|
198
|
+
contents[index].gas_limit = gasLimit.toString();
|
|
199
|
+
patched = true;
|
|
200
|
+
}
|
|
201
|
+
if (!patched) {
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
return {
|
|
205
|
+
...op,
|
|
206
|
+
operation: {
|
|
207
|
+
...op.operation,
|
|
208
|
+
contents: contents,
|
|
209
|
+
},
|
|
210
|
+
};
|
|
211
|
+
}
|
|
88
212
|
async calculateEstimates(op, constants) {
|
|
89
213
|
let feeParams = estimate_1.DEFAULT_FEE_PARAMS;
|
|
90
214
|
try {
|
|
@@ -97,24 +221,61 @@ class RPCEstimateProvider extends provider_1.Provider {
|
|
|
97
221
|
catch {
|
|
98
222
|
// Fall back to L1 defaults when the endpoint is missing or unavailable.
|
|
99
223
|
}
|
|
100
|
-
const
|
|
224
|
+
const forgedOperation = await this.forge(op);
|
|
225
|
+
const { opbytes: initialOpBytes, opOb: { branch, contents }, } = forgedOperation;
|
|
101
226
|
const operation = {
|
|
102
227
|
operation: { branch, contents, signature: STUB_SIGNATURE },
|
|
103
228
|
chain_id: await this.context.readProvider.getChainId(),
|
|
104
229
|
};
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
230
|
+
let currentOperation = operation;
|
|
231
|
+
let opResponse;
|
|
232
|
+
let simulatedOperation;
|
|
233
|
+
let opbytes = initialOpBytes;
|
|
234
|
+
let lastError;
|
|
235
|
+
const maxRebalanceAttempts = (op.simulation?.gasLimitPatchableIndexes?.length ?? 0) + 1;
|
|
236
|
+
for (let attempt = 0; attempt <= maxRebalanceAttempts; attempt++) {
|
|
237
|
+
// Keep PreparedOperation on attempt 0 for provider-level block/counter recovery. Rebalance
|
|
238
|
+
// retries intentionally omit it so patchSimulationGasLimits cannot restore the even split.
|
|
239
|
+
const simulated = await this.simulate(currentOperation, attempt === 0 ? op : undefined);
|
|
240
|
+
opResponse = simulated.opResponse;
|
|
241
|
+
simulatedOperation = simulated.op;
|
|
242
|
+
currentOperation = simulated.op;
|
|
243
|
+
const errors = [...(0, errors_1.flattenErrors)(opResponse, 'backtracked'), ...(0, errors_1.flattenErrors)(opResponse)];
|
|
244
|
+
if (errors.length === 0) {
|
|
245
|
+
break;
|
|
246
|
+
}
|
|
247
|
+
lastError = new errors_1.TezosOperationError(errors, 'Error occurred during estimation', opResponse.contents);
|
|
248
|
+
if (!this.hasOperationGasExhausted(errors)) {
|
|
249
|
+
throw lastError;
|
|
250
|
+
}
|
|
251
|
+
const rebalancedOperation = this.rebalanceGasLimits(currentOperation, opResponse, op, constants);
|
|
252
|
+
if (!rebalancedOperation || attempt === maxRebalanceAttempts) {
|
|
253
|
+
throw lastError;
|
|
254
|
+
}
|
|
255
|
+
currentOperation = rebalancedOperation;
|
|
256
|
+
opResponse = undefined;
|
|
257
|
+
simulatedOperation = undefined;
|
|
258
|
+
}
|
|
259
|
+
if (!opResponse || !simulatedOperation) {
|
|
260
|
+
throw lastError ?? new Error('Unable to simulate operation for estimation');
|
|
111
261
|
}
|
|
262
|
+
if (simulatedOperation !== operation) {
|
|
263
|
+
if (!simulatedOperation.operation.branch) {
|
|
264
|
+
throw new Error('Unable to reforge simulated operation without a branch');
|
|
265
|
+
}
|
|
266
|
+
opbytes = await this.context.forger.forge({
|
|
267
|
+
branch: simulatedOperation.operation.branch,
|
|
268
|
+
contents: simulatedOperation.operation.contents,
|
|
269
|
+
});
|
|
270
|
+
}
|
|
271
|
+
const { cost_per_byte, origination_size } = constants;
|
|
112
272
|
let numberOfOps = 1;
|
|
113
|
-
if (Array.isArray(
|
|
273
|
+
if (Array.isArray(simulatedOperation.operation.contents) &&
|
|
274
|
+
simulatedOperation.operation.contents.length > 1) {
|
|
114
275
|
numberOfOps =
|
|
115
276
|
opResponse.contents[0].kind === 'reveal'
|
|
116
|
-
?
|
|
117
|
-
:
|
|
277
|
+
? simulatedOperation.operation.contents.length - 1
|
|
278
|
+
: simulatedOperation.operation.contents.length;
|
|
118
279
|
}
|
|
119
280
|
return opResponse.contents.map((x) => {
|
|
120
281
|
const content = x;
|
package/dist/lib/version.js
CHANGED
|
@@ -3,6 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.VERSION = void 0;
|
|
4
4
|
// IMPORTANT: THIS FILE IS AUTO GENERATED! DO NOT MANUALLY EDIT!
|
|
5
5
|
exports.VERSION = {
|
|
6
|
-
"commitHash": "
|
|
7
|
-
"version": "
|
|
6
|
+
"commitHash": "13f62cd47ea018312f100b660d0225604c757afa",
|
|
7
|
+
"version": "25.0.0-rc.1"
|
|
8
8
|
};
|
package/dist/taquito.es6.js
CHANGED
|
@@ -219,6 +219,7 @@ var Protocols;
|
|
|
219
219
|
Protocols["PsRiotuma"] = "PsRiotumaAMotcRoDWW1bysEhQy2n1M5fy8JgRp8jjRfHGmfeA7";
|
|
220
220
|
Protocols["PtSeouLou"] = "PtSeouLouXkxhg39oWzjxDWaCydNfR3RxCUrNe4Q9Ro8BTehcbh";
|
|
221
221
|
Protocols["PtTALLiNt"] = "PtTALLiNtPec7mE7yY4m3k26J8Qukef3E3ehzhfXgFZKGtDdAXu";
|
|
222
|
+
Protocols["PsUshuai9"] = "PsUshuai9QapM5TGj1JpuVGkdxz5GykdnEvS6Rh8SUVrARvZLCY";
|
|
222
223
|
Protocols["ProtoALpha"] = "ProtoALphaALphaALphaALphaALphaALphaALphaALphaDdp3zK";
|
|
223
224
|
})(Protocols || (Protocols = {}));
|
|
224
225
|
const protocols = {
|
|
@@ -242,7 +243,8 @@ const protocols = {
|
|
|
242
243
|
'022': [Protocols.PsRiotuma],
|
|
243
244
|
'023': [Protocols.PtSeouLou],
|
|
244
245
|
'024': [Protocols.PtTALLiNt],
|
|
245
|
-
'025': [Protocols.
|
|
246
|
+
'025': [Protocols.PsUshuai9],
|
|
247
|
+
'026': [Protocols.ProtoALpha],
|
|
246
248
|
};
|
|
247
249
|
var ChainIds;
|
|
248
250
|
(function (ChainIds) {
|
|
@@ -269,6 +271,7 @@ var ChainIds;
|
|
|
269
271
|
ChainIds["RIONET"] = "NetXPdgaoabtBth";
|
|
270
272
|
ChainIds["SEOULNET"] = "NetXd56aBs1aeW3";
|
|
271
273
|
ChainIds["TALLINNNET"] = "NetXe8DbhW9A1eS";
|
|
274
|
+
ChainIds["USHUAIANET"] = "NetXpX8WSZkAZZA";
|
|
272
275
|
})(ChainIds || (ChainIds = {}));
|
|
273
276
|
const getRevealGasLimit = (address) => Math.round((getRevealGasLimitInternal(address) * 37) / 10);
|
|
274
277
|
const getRevealGasLimitInternal = (address) => {
|
|
@@ -3886,6 +3889,15 @@ class RevealEstimateError extends TaquitoError {
|
|
|
3886
3889
|
this.message = 'Public key is unknown, unable to estimate the reveal operation in Wallet API.';
|
|
3887
3890
|
}
|
|
3888
3891
|
}
|
|
3892
|
+
class BatchGasLimitExceededError extends TaquitoError {
|
|
3893
|
+
constructor(requiredGasLimit, hardGasLimitPerBlock) {
|
|
3894
|
+
super();
|
|
3895
|
+
this.requiredGasLimit = requiredGasLimit;
|
|
3896
|
+
this.hardGasLimitPerBlock = hardGasLimitPerBlock;
|
|
3897
|
+
this.name = 'BatchGasLimitExceededError';
|
|
3898
|
+
this.message = `Batch gas estimation requires at least ${requiredGasLimit} gas, which exceeds the per-block limit of ${hardGasLimitPerBlock}. Split the batch into smaller operations.`;
|
|
3899
|
+
}
|
|
3900
|
+
}
|
|
3889
3901
|
|
|
3890
3902
|
// stub signature that won't be verified by tezos rpc simulate_operation
|
|
3891
3903
|
const STUB_SIGNATURE = 'edsigtkpiSSschcaCt9pUVrpNPf7TTcgvgDEDD6NCEHMy8NNQJCGnMfLZzYoQj74yLjo9wx6MPVV29CvVzgi7qEcEUok3k7AuMg';
|
|
@@ -3904,6 +3916,7 @@ class RPCEstimateProvider extends Provider {
|
|
|
3904
3916
|
this.REVEAL_LENGTH_TZ4 = 622; // injecting size tz4=620
|
|
3905
3917
|
this.MILLIGAS_BUFFER = 100 * 1000; // 100 buffer depends on operation kind
|
|
3906
3918
|
this.STORAGE_BUFFER = 20; // according to octez-client
|
|
3919
|
+
this.UNKNOWN_GAS_LIMIT_PER_OPERATION = 1000;
|
|
3907
3920
|
this.prepare = new PrepareProvider(this.context);
|
|
3908
3921
|
}
|
|
3909
3922
|
async getKeys() {
|
|
@@ -3961,6 +3974,129 @@ class RPCEstimateProvider extends Provider {
|
|
|
3961
3974
|
};
|
|
3962
3975
|
}
|
|
3963
3976
|
}
|
|
3977
|
+
hasOperationGasExhausted(errors) {
|
|
3978
|
+
return errors.some((error) => error.id.endsWith('gas_exhausted.operation'));
|
|
3979
|
+
}
|
|
3980
|
+
getOperationResult(content) {
|
|
3981
|
+
return content?.metadata?.operation_result;
|
|
3982
|
+
}
|
|
3983
|
+
getInternalOperationResults(content) {
|
|
3984
|
+
const internalResults = content?.metadata?.internal_operation_results;
|
|
3985
|
+
return Array.isArray(internalResults) ? internalResults : [];
|
|
3986
|
+
}
|
|
3987
|
+
operationResultHasGasExhausted(result) {
|
|
3988
|
+
return Array.isArray(result?.errors)
|
|
3989
|
+
? result.errors.some((error) => error.id?.endsWith('gas_exhausted.operation'))
|
|
3990
|
+
: false;
|
|
3991
|
+
}
|
|
3992
|
+
findGasExhaustedContentIndex(contents) {
|
|
3993
|
+
const directFailureIndex = contents.findIndex((content) => this.operationResultHasGasExhausted(this.getOperationResult(content)));
|
|
3994
|
+
if (directFailureIndex !== -1) {
|
|
3995
|
+
return directFailureIndex;
|
|
3996
|
+
}
|
|
3997
|
+
const internalFailureIndex = contents.findIndex((content) => this.getInternalOperationResults(content).some((internalResult) => this.operationResultHasGasExhausted(internalResult.result)));
|
|
3998
|
+
if (internalFailureIndex !== -1) {
|
|
3999
|
+
return internalFailureIndex;
|
|
4000
|
+
}
|
|
4001
|
+
const firstSkippedIndex = contents.findIndex((content) => this.getOperationResult(content)?.status === 'skipped');
|
|
4002
|
+
return firstSkippedIndex > 0 ? firstSkippedIndex - 1 : -1;
|
|
4003
|
+
}
|
|
4004
|
+
getContentGasLimit(content) {
|
|
4005
|
+
const gasLimit = Number(content?.gas_limit);
|
|
4006
|
+
return Number.isFinite(gasLimit) && gasLimit >= 0 ? gasLimit : 0;
|
|
4007
|
+
}
|
|
4008
|
+
getMeasuredGasLimit(content, hardGasLimitPerOperation) {
|
|
4009
|
+
const operationResults = flattenOperationResult({ contents: [content] });
|
|
4010
|
+
const consumedMilligas = operationResults.reduce((total, result) => total + (Number(result.consumed_milligas) || 0), 0);
|
|
4011
|
+
if (consumedMilligas <= 0) {
|
|
4012
|
+
return;
|
|
4013
|
+
}
|
|
4014
|
+
const safetyGas = isOpWithGasBuffer(content) ? this.MILLIGAS_BUFFER / 1000 : 0;
|
|
4015
|
+
return Math.min(Math.ceil(consumedMilligas / 1000) + safetyGas, hardGasLimitPerOperation);
|
|
4016
|
+
}
|
|
4017
|
+
rebalanceGasLimits(op, opResponse, preparedOperation, constants) {
|
|
4018
|
+
const hardGasLimitPerOperation = Number(constants.hard_gas_limit_per_operation);
|
|
4019
|
+
const hardGasLimitPerBlock = Number(constants.hard_gas_limit_per_block);
|
|
4020
|
+
const patchableIndexes = preparedOperation.simulation?.gasLimitPatchableIndexes?.filter((index) => index >= 0 && index < opResponse.contents.length);
|
|
4021
|
+
if (!Array.isArray(op.operation.contents) ||
|
|
4022
|
+
!patchableIndexes?.length ||
|
|
4023
|
+
!Number.isFinite(hardGasLimitPerOperation) ||
|
|
4024
|
+
!Number.isFinite(hardGasLimitPerBlock)) {
|
|
4025
|
+
return;
|
|
4026
|
+
}
|
|
4027
|
+
const responseContents = opResponse.contents;
|
|
4028
|
+
const starvedIndex = this.findGasExhaustedContentIndex(responseContents);
|
|
4029
|
+
if (starvedIndex === -1 || !patchableIndexes.includes(starvedIndex)) {
|
|
4030
|
+
return;
|
|
4031
|
+
}
|
|
4032
|
+
const patchableIndexSet = new Set(patchableIndexes);
|
|
4033
|
+
const contents = op.operation.contents.map((content) => ({
|
|
4034
|
+
...content,
|
|
4035
|
+
}));
|
|
4036
|
+
const patchedGasLimits = new Map();
|
|
4037
|
+
let fixedGasTotal = 0;
|
|
4038
|
+
let measuredGasTotal = 0;
|
|
4039
|
+
const unknownPatchableIndexes = [];
|
|
4040
|
+
for (const [index, content] of responseContents.entries()) {
|
|
4041
|
+
if (!patchableIndexSet.has(index)) {
|
|
4042
|
+
fixedGasTotal += this.getContentGasLimit(contents[index]);
|
|
4043
|
+
continue;
|
|
4044
|
+
}
|
|
4045
|
+
if (index === starvedIndex) {
|
|
4046
|
+
continue;
|
|
4047
|
+
}
|
|
4048
|
+
const status = this.getOperationResult(content)?.status;
|
|
4049
|
+
const measuredGasLimit = status === 'applied' || status === 'backtracked'
|
|
4050
|
+
? this.getMeasuredGasLimit(content, hardGasLimitPerOperation)
|
|
4051
|
+
: undefined;
|
|
4052
|
+
if (typeof measuredGasLimit === 'number') {
|
|
4053
|
+
patchedGasLimits.set(index, measuredGasLimit);
|
|
4054
|
+
measuredGasTotal += measuredGasLimit;
|
|
4055
|
+
}
|
|
4056
|
+
else {
|
|
4057
|
+
unknownPatchableIndexes.push(index);
|
|
4058
|
+
}
|
|
4059
|
+
}
|
|
4060
|
+
const requiredKnownGas = fixedGasTotal + measuredGasTotal;
|
|
4061
|
+
if (requiredKnownGas > hardGasLimitPerBlock) {
|
|
4062
|
+
throw new BatchGasLimitExceededError(requiredKnownGas, hardGasLimitPerBlock);
|
|
4063
|
+
}
|
|
4064
|
+
const gasAvailableAfterKnown = hardGasLimitPerBlock - requiredKnownGas;
|
|
4065
|
+
const minimumUnknownGas = unknownPatchableIndexes.length + 1;
|
|
4066
|
+
if (gasAvailableAfterKnown < minimumUnknownGas) {
|
|
4067
|
+
throw new BatchGasLimitExceededError(requiredKnownGas + minimumUnknownGas, hardGasLimitPerBlock);
|
|
4068
|
+
}
|
|
4069
|
+
const unknownGasLimit = unknownPatchableIndexes.length > 0
|
|
4070
|
+
? Math.min(this.UNKNOWN_GAS_LIMIT_PER_OPERATION, Math.floor((gasAvailableAfterKnown - 1) / unknownPatchableIndexes.length))
|
|
4071
|
+
: 0;
|
|
4072
|
+
const gasReservedForUnknown = unknownGasLimit * unknownPatchableIndexes.length;
|
|
4073
|
+
const starvedGasLimit = Math.min(hardGasLimitPerOperation, gasAvailableAfterKnown - gasReservedForUnknown);
|
|
4074
|
+
if (starvedGasLimit <= 0) {
|
|
4075
|
+
return;
|
|
4076
|
+
}
|
|
4077
|
+
patchedGasLimits.set(starvedIndex, starvedGasLimit);
|
|
4078
|
+
for (const index of unknownPatchableIndexes) {
|
|
4079
|
+
patchedGasLimits.set(index, unknownGasLimit);
|
|
4080
|
+
}
|
|
4081
|
+
let patched = false;
|
|
4082
|
+
for (const [index, gasLimit] of patchedGasLimits.entries()) {
|
|
4083
|
+
if (this.getContentGasLimit(contents[index]) === gasLimit) {
|
|
4084
|
+
continue;
|
|
4085
|
+
}
|
|
4086
|
+
contents[index].gas_limit = gasLimit.toString();
|
|
4087
|
+
patched = true;
|
|
4088
|
+
}
|
|
4089
|
+
if (!patched) {
|
|
4090
|
+
return;
|
|
4091
|
+
}
|
|
4092
|
+
return {
|
|
4093
|
+
...op,
|
|
4094
|
+
operation: {
|
|
4095
|
+
...op.operation,
|
|
4096
|
+
contents: contents,
|
|
4097
|
+
},
|
|
4098
|
+
};
|
|
4099
|
+
}
|
|
3964
4100
|
async calculateEstimates(op, constants) {
|
|
3965
4101
|
let feeParams = DEFAULT_FEE_PARAMS;
|
|
3966
4102
|
try {
|
|
@@ -3973,24 +4109,61 @@ class RPCEstimateProvider extends Provider {
|
|
|
3973
4109
|
catch {
|
|
3974
4110
|
// Fall back to L1 defaults when the endpoint is missing or unavailable.
|
|
3975
4111
|
}
|
|
3976
|
-
const
|
|
4112
|
+
const forgedOperation = await this.forge(op);
|
|
4113
|
+
const { opbytes: initialOpBytes, opOb: { branch, contents }, } = forgedOperation;
|
|
3977
4114
|
const operation = {
|
|
3978
4115
|
operation: { branch, contents, signature: STUB_SIGNATURE },
|
|
3979
4116
|
chain_id: await this.context.readProvider.getChainId(),
|
|
3980
4117
|
};
|
|
3981
|
-
|
|
3982
|
-
|
|
3983
|
-
|
|
3984
|
-
|
|
3985
|
-
|
|
3986
|
-
|
|
4118
|
+
let currentOperation = operation;
|
|
4119
|
+
let opResponse;
|
|
4120
|
+
let simulatedOperation;
|
|
4121
|
+
let opbytes = initialOpBytes;
|
|
4122
|
+
let lastError;
|
|
4123
|
+
const maxRebalanceAttempts = (op.simulation?.gasLimitPatchableIndexes?.length ?? 0) + 1;
|
|
4124
|
+
for (let attempt = 0; attempt <= maxRebalanceAttempts; attempt++) {
|
|
4125
|
+
// Keep PreparedOperation on attempt 0 for provider-level block/counter recovery. Rebalance
|
|
4126
|
+
// retries intentionally omit it so patchSimulationGasLimits cannot restore the even split.
|
|
4127
|
+
const simulated = await this.simulate(currentOperation, attempt === 0 ? op : undefined);
|
|
4128
|
+
opResponse = simulated.opResponse;
|
|
4129
|
+
simulatedOperation = simulated.op;
|
|
4130
|
+
currentOperation = simulated.op;
|
|
4131
|
+
const errors = [...flattenErrors(opResponse, 'backtracked'), ...flattenErrors(opResponse)];
|
|
4132
|
+
if (errors.length === 0) {
|
|
4133
|
+
break;
|
|
4134
|
+
}
|
|
4135
|
+
lastError = new TezosOperationError(errors, 'Error occurred during estimation', opResponse.contents);
|
|
4136
|
+
if (!this.hasOperationGasExhausted(errors)) {
|
|
4137
|
+
throw lastError;
|
|
4138
|
+
}
|
|
4139
|
+
const rebalancedOperation = this.rebalanceGasLimits(currentOperation, opResponse, op, constants);
|
|
4140
|
+
if (!rebalancedOperation || attempt === maxRebalanceAttempts) {
|
|
4141
|
+
throw lastError;
|
|
4142
|
+
}
|
|
4143
|
+
currentOperation = rebalancedOperation;
|
|
4144
|
+
opResponse = undefined;
|
|
4145
|
+
simulatedOperation = undefined;
|
|
3987
4146
|
}
|
|
4147
|
+
if (!opResponse || !simulatedOperation) {
|
|
4148
|
+
throw lastError ?? new Error('Unable to simulate operation for estimation');
|
|
4149
|
+
}
|
|
4150
|
+
if (simulatedOperation !== operation) {
|
|
4151
|
+
if (!simulatedOperation.operation.branch) {
|
|
4152
|
+
throw new Error('Unable to reforge simulated operation without a branch');
|
|
4153
|
+
}
|
|
4154
|
+
opbytes = await this.context.forger.forge({
|
|
4155
|
+
branch: simulatedOperation.operation.branch,
|
|
4156
|
+
contents: simulatedOperation.operation.contents,
|
|
4157
|
+
});
|
|
4158
|
+
}
|
|
4159
|
+
const { cost_per_byte, origination_size } = constants;
|
|
3988
4160
|
let numberOfOps = 1;
|
|
3989
|
-
if (Array.isArray(
|
|
4161
|
+
if (Array.isArray(simulatedOperation.operation.contents) &&
|
|
4162
|
+
simulatedOperation.operation.contents.length > 1) {
|
|
3990
4163
|
numberOfOps =
|
|
3991
4164
|
opResponse.contents[0].kind === 'reveal'
|
|
3992
|
-
?
|
|
3993
|
-
:
|
|
4165
|
+
? simulatedOperation.operation.contents.length - 1
|
|
4166
|
+
: simulatedOperation.operation.contents.length;
|
|
3994
4167
|
}
|
|
3995
4168
|
return opResponse.contents.map((x) => {
|
|
3996
4169
|
const content = x;
|
|
@@ -7575,8 +7748,8 @@ class Context {
|
|
|
7575
7748
|
|
|
7576
7749
|
// IMPORTANT: THIS FILE IS AUTO GENERATED! DO NOT MANUALLY EDIT!
|
|
7577
7750
|
const VERSION = {
|
|
7578
|
-
"commitHash": "
|
|
7579
|
-
"version": "
|
|
7751
|
+
"commitHash": "13f62cd47ea018312f100b660d0225604c757afa",
|
|
7752
|
+
"version": "25.0.0-rc.1"
|
|
7580
7753
|
};
|
|
7581
7754
|
|
|
7582
7755
|
/**
|
|
@@ -8052,5 +8225,5 @@ class TezosToolkit {
|
|
|
8052
8225
|
}
|
|
8053
8226
|
}
|
|
8054
8227
|
|
|
8055
|
-
export { BallotOperation, BatchOperation, BigMapAbstraction, COST_PER_BYTE, ChainIds, CompositeForger, Context, ContractAbstraction, ContractMethodObject, ContractView, DEFAULT_FEE_PARAMS, DEFAULT_SMART_CONTRACT_METHOD_NAME, DefaultGlobalConstantsProvider, DelegateOperation, DelegationWalletOperation, DrainDelegateOperation, Estimate, GlobalConstantNotFound, IncreasePaidStorageOperation, InvalidBalanceError, InvalidCodeParameter, InvalidDelegationSource, InvalidEstimateValueError, InvalidInitParameter, InvalidParameterError, InvalidViewSimulationContext, LegacyWalletProvider, MANAGER_LAMBDA, MichelCodecPacker, MichelCodecParser, NoopParser, ORIGINATION_SIZE, ObservableSubscription, Operation, OperationBatch, OriginationOperation, OriginationParameterError, OriginationWalletOperation, PollingSubscribeProvider, PrepareProvider, ProposalsOperation, Protocols, REVEAL_STORAGE_LIMIT, RPCEstimateProvider, RegisterGlobalConstantOperation, RegisterGlobalConstantWalletOperation, RevealEstimateError, RevealOperation, RevealOperationError, RpcForger, RpcInjector, RpcPacker, RpcReadAdapter, SaplingStateAbstraction, SmartRollupAddMessagesOperation, SmartRollupOriginateOperation, TaquitoLocalForger, TezosOperationError, TezosPreapplyFailureError, TezosToolkit, TransactionOperation, TransactionWalletOperation, TransferTicketOperation, TransferTicketWalletOperation, UnconfiguredGlobalConstantsProviderError, UpdateCompanionKeyOperation, UpdateConsensusKeyOperation, VIEW_LAMBDA, ViewSimulationError, Wallet, WalletOperation, WalletOperationBatch, attachKind, compose, createActivationOperation, createBallotOperation, createDrainDelegateOperation, createIncreasePaidStorageOperation, createOriginationOperation, createProposalsOperation, createRegisterDelegateOperation, createRegisterGlobalConstantOperation, createRevealOperation, createSetDelegateOperation, createSmartRollupAddMessagesOperation, createSmartRollupExecuteOutboxMessageOperation, createSmartRollupOriginateOperation, createTransferOperation, createTransferTicketOperation, createUpdateCompanionKeyOperation, createUpdateConsensusKeyOperation, defaultConfigConfirmation, feeParamsFromMempoolFilter, findWithKind, getRevealFee, getRevealFeeInternal, getRevealGasLimit, hasMetadata, hasMetadataWithInternalOperationResult, hasMetadataWithResult, importKey, isKind, isOpRequireReveal, isOpWithFee, isOpWithGasBuffer, isSourceOp, protocols, smartContractAbstractionSemantic, validateAndExtractFailwith };
|
|
8228
|
+
export { BallotOperation, BatchGasLimitExceededError, BatchOperation, BigMapAbstraction, COST_PER_BYTE, ChainIds, CompositeForger, Context, ContractAbstraction, ContractMethodObject, ContractView, DEFAULT_FEE_PARAMS, DEFAULT_SMART_CONTRACT_METHOD_NAME, DefaultGlobalConstantsProvider, DelegateOperation, DelegationWalletOperation, DrainDelegateOperation, Estimate, GlobalConstantNotFound, IncreasePaidStorageOperation, InvalidBalanceError, InvalidCodeParameter, InvalidDelegationSource, InvalidEstimateValueError, InvalidInitParameter, InvalidParameterError, InvalidViewSimulationContext, LegacyWalletProvider, MANAGER_LAMBDA, MichelCodecPacker, MichelCodecParser, NoopParser, ORIGINATION_SIZE, ObservableSubscription, Operation, OperationBatch, OriginationOperation, OriginationParameterError, OriginationWalletOperation, PollingSubscribeProvider, PrepareProvider, ProposalsOperation, Protocols, REVEAL_STORAGE_LIMIT, RPCEstimateProvider, RegisterGlobalConstantOperation, RegisterGlobalConstantWalletOperation, RevealEstimateError, RevealOperation, RevealOperationError, RpcForger, RpcInjector, RpcPacker, RpcReadAdapter, SaplingStateAbstraction, SmartRollupAddMessagesOperation, SmartRollupOriginateOperation, TaquitoLocalForger, TezosOperationError, TezosPreapplyFailureError, TezosToolkit, TransactionOperation, TransactionWalletOperation, TransferTicketOperation, TransferTicketWalletOperation, UnconfiguredGlobalConstantsProviderError, UpdateCompanionKeyOperation, UpdateConsensusKeyOperation, VIEW_LAMBDA, ViewSimulationError, Wallet, WalletOperation, WalletOperationBatch, attachKind, compose, createActivationOperation, createBallotOperation, createDrainDelegateOperation, createIncreasePaidStorageOperation, createOriginationOperation, createProposalsOperation, createRegisterDelegateOperation, createRegisterGlobalConstantOperation, createRevealOperation, createSetDelegateOperation, createSmartRollupAddMessagesOperation, createSmartRollupExecuteOutboxMessageOperation, createSmartRollupOriginateOperation, createTransferOperation, createTransferTicketOperation, createUpdateCompanionKeyOperation, createUpdateConsensusKeyOperation, defaultConfigConfirmation, feeParamsFromMempoolFilter, findWithKind, getRevealFee, getRevealFeeInternal, getRevealGasLimit, hasMetadata, hasMetadataWithInternalOperationResult, hasMetadataWithResult, importKey, isKind, isOpRequireReveal, isOpWithFee, isOpWithGasBuffer, isSourceOp, protocols, smartContractAbstractionSemantic, validateAndExtractFailwith };
|
|
8056
8229
|
//# sourceMappingURL=taquito.es6.js.map
|
package/dist/taquito.es6.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"taquito.es6.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"taquito.es6.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|