@algorandfoundation/algokit-utils 7.0.0-beta.16 → 7.0.0-beta.18
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/app-deploy.js.map +1 -1
- package/app-deploy.mjs +2 -2
- package/app-deploy.mjs.map +1 -1
- package/app.d.ts +2 -2
- package/app.js +2 -2
- package/app.js.map +1 -1
- package/app.mjs +2 -2
- package/app.mjs.map +1 -1
- package/package.json +1 -1
- package/transaction/legacy-bridge.js.map +1 -1
- package/transaction/legacy-bridge.mjs +2 -2
- package/transaction/legacy-bridge.mjs.map +1 -1
- package/transaction/transaction.d.ts +8 -15
- package/transaction/transaction.js +7 -7
- package/transaction/transaction.js.map +1 -1
- package/transaction/transaction.mjs +7 -7
- package/transaction/transaction.mjs.map +1 -1
- package/types/account-manager.js.map +1 -1
- package/types/account-manager.mjs +2 -2
- package/types/account-manager.mjs.map +1 -1
- package/types/algorand-client-interface.d.ts +2 -2
- package/types/algorand-client-transaction-creator.d.ts +3 -3
- package/types/algorand-client-transaction-creator.js +1 -1
- package/types/algorand-client-transaction-creator.js.map +1 -1
- package/types/algorand-client-transaction-creator.mjs +1 -1
- package/types/algorand-client-transaction-creator.mjs.map +1 -1
- package/types/algorand-client-transaction-sender.d.ts +4 -4
- package/types/algorand-client-transaction-sender.js +1 -1
- package/types/algorand-client-transaction-sender.js.map +1 -1
- package/types/algorand-client-transaction-sender.mjs +1 -1
- package/types/algorand-client-transaction-sender.mjs.map +1 -1
- package/types/algorand-client.d.ts +3 -3
- package/types/algorand-client.js +1 -1
- package/types/algorand-client.js.map +1 -1
- package/types/algorand-client.mjs +3 -3
- package/types/algorand-client.mjs.map +1 -1
- package/types/app-arc56.d.ts +20 -10
- package/types/app-arc56.js.map +1 -1
- package/types/app-arc56.mjs.map +1 -1
- package/types/app-client.d.ts +9 -6
- package/types/app-client.js +99 -12
- package/types/app-client.js.map +1 -1
- package/types/app-client.mjs +99 -12
- package/types/app-client.mjs.map +1 -1
- package/types/app-deployer.js.map +1 -1
- package/types/app-deployer.mjs +2 -2
- package/types/app-deployer.mjs.map +1 -1
- package/types/app.d.ts +3 -3
- package/types/app.js.map +1 -1
- package/types/app.mjs.map +1 -1
- package/types/asset-manager.d.ts +4 -4
- package/types/asset-manager.js +2 -2
- package/types/asset-manager.js.map +1 -1
- package/types/asset-manager.mjs +2 -2
- package/types/asset-manager.mjs.map +1 -1
- package/types/composer.d.ts +21 -21
- package/types/composer.js +9 -10
- package/types/composer.js.map +1 -1
- package/types/composer.mjs +9 -10
- package/types/composer.mjs.map +1 -1
- package/types/kmd-account-manager.js.map +1 -1
- package/types/kmd-account-manager.mjs +2 -2
- package/types/kmd-account-manager.mjs.map +1 -1
- package/types/logic-error.d.ts +2 -3
- package/types/logic-error.js +3 -3
- package/types/logic-error.js.map +1 -1
- package/types/logic-error.mjs +3 -3
- package/types/logic-error.mjs.map +1 -1
package/types/app-client.mjs
CHANGED
|
@@ -40,6 +40,57 @@ function getDeployTimeControl(approval, appSpec, templateVariableName, callConfi
|
|
|
40
40
|
return !!abiCallConfig && abiCallConfig !== 'NEVER';
|
|
41
41
|
});
|
|
42
42
|
}
|
|
43
|
+
const BYTE_CBLOCK = 38;
|
|
44
|
+
const INT_CBLOCK = 32;
|
|
45
|
+
/**
|
|
46
|
+
* Get the offset of the last constant block at the beginning of the program
|
|
47
|
+
* This value is used to calculate the program counter for an ARC56 program that has a pcOffsetMethod of "cblocks"
|
|
48
|
+
*
|
|
49
|
+
* @param program The program to parse
|
|
50
|
+
* @returns The PC value of the opcode after the last constant block
|
|
51
|
+
*/
|
|
52
|
+
function getConstantBlockOffset(program) {
|
|
53
|
+
const bytes = [...program];
|
|
54
|
+
const programSize = bytes.length;
|
|
55
|
+
bytes.shift(); // remove version
|
|
56
|
+
/** The PC of the opcode after the bytecblock */
|
|
57
|
+
let bytecblockOffset;
|
|
58
|
+
/** The PC of the opcode after the intcblock */
|
|
59
|
+
let intcblockOffset;
|
|
60
|
+
while (bytes.length > 0) {
|
|
61
|
+
/** The current byte from the beginning of the byte array */
|
|
62
|
+
const byte = bytes.shift();
|
|
63
|
+
// If the byte is a constant block...
|
|
64
|
+
if (byte === BYTE_CBLOCK || byte === INT_CBLOCK) {
|
|
65
|
+
const isBytecblock = byte === BYTE_CBLOCK;
|
|
66
|
+
/** The byte following the opcode is the number of values in the constant block */
|
|
67
|
+
const valuesRemaining = bytes.shift();
|
|
68
|
+
// Iterate over all the values in the constant block
|
|
69
|
+
for (let i = 0; i < valuesRemaining; i++) {
|
|
70
|
+
if (isBytecblock) {
|
|
71
|
+
/** The byte following the opcode is the length of the next element */
|
|
72
|
+
const length = bytes.shift();
|
|
73
|
+
bytes.splice(0, length);
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
// intcblock is a uvarint, so we need to keep reading until we find the end (MSB is not set)
|
|
77
|
+
while ((bytes.shift() & 0x80) !== 0) {
|
|
78
|
+
// Do nothing...
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
if (isBytecblock)
|
|
83
|
+
bytecblockOffset = programSize - bytes.length - 1;
|
|
84
|
+
else
|
|
85
|
+
intcblockOffset = programSize - bytes.length - 1;
|
|
86
|
+
if (bytes[0] !== BYTE_CBLOCK && bytes[0] !== INT_CBLOCK) {
|
|
87
|
+
// if the next opcode isn't a constant block, we're done
|
|
88
|
+
break;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return Math.max(bytecblockOffset ?? 0, intcblockOffset ?? 0);
|
|
93
|
+
}
|
|
43
94
|
/** ARC-56/ARC-32 application client that allows you to manage calls and
|
|
44
95
|
* state for a specific deployed instance of an app (with a known app ID). */
|
|
45
96
|
class AppClient {
|
|
@@ -72,7 +123,7 @@ class AppClient {
|
|
|
72
123
|
bare: this.getBareSendMethods(),
|
|
73
124
|
};
|
|
74
125
|
}
|
|
75
|
-
/** Start a new `
|
|
126
|
+
/** Start a new `TransactionComposer` transaction group */
|
|
76
127
|
newGroup() {
|
|
77
128
|
return this._algorand.newGroup();
|
|
78
129
|
}
|
|
@@ -281,11 +332,19 @@ class AppClient {
|
|
|
281
332
|
* @param isClearStateProgram Whether or not the code was running the clear state program (defaults to approval program)
|
|
282
333
|
* @returns The new error, or if there was no logic error or source map then the wrapped error with source details
|
|
283
334
|
*/
|
|
284
|
-
exposeLogicError(e, isClearStateProgram) {
|
|
335
|
+
async exposeLogicError(e, isClearStateProgram) {
|
|
336
|
+
const pcOffsetMethod = this._appSpec.sourceInfo?.[isClearStateProgram ? 'clear' : 'approval']?.pcOffsetMethod;
|
|
337
|
+
let program;
|
|
338
|
+
if (pcOffsetMethod === 'cblocks') {
|
|
339
|
+
// TODO: Cache this if we deploy the app and it's not updateable
|
|
340
|
+
const appInfo = await this._algorand.app.getById(this.appId);
|
|
341
|
+
program = isClearStateProgram ? appInfo.clearStateProgram : appInfo.approvalProgram;
|
|
342
|
+
}
|
|
285
343
|
return AppClient.exposeLogicError(e, this._appSpec, {
|
|
286
344
|
isClearStateProgram,
|
|
287
345
|
approvalSourceMap: this._approvalSourceMap,
|
|
288
346
|
clearSourceMap: this._clearSourceMap,
|
|
347
|
+
program,
|
|
289
348
|
});
|
|
290
349
|
}
|
|
291
350
|
/**
|
|
@@ -360,17 +419,45 @@ class AppClient {
|
|
|
360
419
|
* @returns The new error, or if there was no logic error or source map then the wrapped error with source details
|
|
361
420
|
*/
|
|
362
421
|
static exposeLogicError(e, appSpec, details) {
|
|
363
|
-
const { isClearStateProgram, approvalSourceMap, clearSourceMap } = details;
|
|
364
|
-
|
|
365
|
-
return e;
|
|
422
|
+
const { isClearStateProgram, approvalSourceMap, clearSourceMap, program } = details;
|
|
423
|
+
const sourceMap = isClearStateProgram ? clearSourceMap : approvalSourceMap;
|
|
366
424
|
const errorDetails = LogicError.parseLogicError(e);
|
|
367
|
-
|
|
368
|
-
if (errorDetails
|
|
425
|
+
// Return the error if we don't have a PC
|
|
426
|
+
if (errorDetails === undefined || errorDetails?.pc === undefined)
|
|
427
|
+
return e;
|
|
428
|
+
/** The PC value to find in the ARC56 SourceInfo */
|
|
429
|
+
let arc56Pc = errorDetails?.pc;
|
|
430
|
+
const programSourceInfo = isClearStateProgram ? appSpec.sourceInfo?.clear : appSpec.sourceInfo?.approval;
|
|
431
|
+
/** The offset to apply to the PC if using the cblocks pc offset method */
|
|
432
|
+
let cblocksOffset = 0;
|
|
433
|
+
// If the program uses cblocks offset, then we need to adjust the PC accordingly
|
|
434
|
+
if (programSourceInfo?.pcOffsetMethod === 'cblocks') {
|
|
435
|
+
if (program === undefined)
|
|
436
|
+
throw new Error('Program bytes are required to calculate the ARC56 cblocks PC offset');
|
|
437
|
+
cblocksOffset = getConstantBlockOffset(program);
|
|
438
|
+
arc56Pc = errorDetails.pc - cblocksOffset;
|
|
439
|
+
}
|
|
440
|
+
// Find the source info for this PC and get the error message
|
|
441
|
+
const sourceInfo = programSourceInfo?.sourceInfo.find((s) => s.pc.includes(arc56Pc));
|
|
442
|
+
const errorMessage = sourceInfo?.errorMessage;
|
|
443
|
+
// If we have the source we can display the TEAL in the error message
|
|
444
|
+
if (appSpec.source) {
|
|
445
|
+
let getLineForPc = (inputPc) => sourceMap?.getLineForPc?.(inputPc);
|
|
446
|
+
// If the SourceMap is not defined, we need to provide our own function for going from a PC to TEAL based on ARC56 SourceInfo[]
|
|
447
|
+
if (sourceMap === undefined) {
|
|
448
|
+
getLineForPc = (inputPc) => {
|
|
449
|
+
const teal = programSourceInfo?.sourceInfo.find((s) => s.pc.includes(inputPc - cblocksOffset))?.teal;
|
|
450
|
+
if (teal === undefined)
|
|
451
|
+
return undefined;
|
|
452
|
+
return teal - 1;
|
|
453
|
+
};
|
|
454
|
+
}
|
|
369
455
|
e = new LogicError(errorDetails, Buffer.from(isClearStateProgram ? appSpec.source.clear : appSpec.source.approval, 'base64')
|
|
370
456
|
.toString()
|
|
371
457
|
.split('\n'),
|
|
372
458
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
373
|
-
|
|
459
|
+
getLineForPc);
|
|
460
|
+
}
|
|
374
461
|
if (errorMessage) {
|
|
375
462
|
const appId = JSON.stringify(e).match(/(?<=app=)\d+/)?.[0] || '';
|
|
376
463
|
const txId = JSON.stringify(e).match(/(?<=transaction )\S+(?=:)/)?.[0];
|
|
@@ -751,7 +838,7 @@ class AppClient {
|
|
|
751
838
|
return await call();
|
|
752
839
|
}
|
|
753
840
|
catch (e) {
|
|
754
|
-
throw this.exposeLogicError(e);
|
|
841
|
+
throw await this.exposeLogicError(e);
|
|
755
842
|
}
|
|
756
843
|
}
|
|
757
844
|
getBoxMethods() {
|
|
@@ -1115,7 +1202,7 @@ class ApplicationClient {
|
|
|
1115
1202
|
return { ...result, ...{ compiledApproval: approvalCompiled, compiledClear: clearCompiled } };
|
|
1116
1203
|
}
|
|
1117
1204
|
catch (e) {
|
|
1118
|
-
throw this.exposeLogicError(e);
|
|
1205
|
+
throw await this.exposeLogicError(e);
|
|
1119
1206
|
}
|
|
1120
1207
|
}
|
|
1121
1208
|
/**
|
|
@@ -1149,7 +1236,7 @@ class ApplicationClient {
|
|
|
1149
1236
|
return { ...result, ...{ compiledApproval: approvalCompiled, compiledClear: clearCompiled } };
|
|
1150
1237
|
}
|
|
1151
1238
|
catch (e) {
|
|
1152
|
-
throw this.exposeLogicError(e);
|
|
1239
|
+
throw await this.exposeLogicError(e);
|
|
1153
1240
|
}
|
|
1154
1241
|
}
|
|
1155
1242
|
/**
|
|
@@ -1502,7 +1589,7 @@ class ApplicationClient {
|
|
|
1502
1589
|
.toString()
|
|
1503
1590
|
.split('\n'),
|
|
1504
1591
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
1505
|
-
isClear ? this._clearSourceMap : this._approvalSourceMap);
|
|
1592
|
+
(pc) => (isClear ? this._clearSourceMap : this._approvalSourceMap).getLineForPc(pc));
|
|
1506
1593
|
else
|
|
1507
1594
|
return e;
|
|
1508
1595
|
}
|