Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4,898 changes: 3,313 additions & 1,585 deletions package-lock.json

Large diffs are not rendered by default.

7 changes: 4 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -69,23 +69,23 @@
"pre-commit": "npm run lint && npm run typecheck && npm run format"
},
"dependencies": {
"@algorandfoundation/algokit-utils": "10.0.0-alpha.45",
"@noble/hashes": "^2.0.1",
"@vscode/debugadapter": "^1.64.0",
"algosdk": "^3.0.0",
"await-notify": "^1.0.1"
},
"devDependencies": {
"semantic-release": "^24.1.2",
"@istanbuljs/nyc-config-typescript": "^1.0.2",
"@types/glob": "^7.2.0",
"@types/lodash": "^4.14.196",
"@types/mocha": "^9.1.0",
"@types/node": "^14.14.37",
"@types/vscode": "^1.66.0",
"conventional-changelog-conventionalcommits": "8.0.0",
"@typescript-eslint/eslint-plugin": "^5.62.0",
"@typescript-eslint/parser": "^5.62.0",
"@vscode/debugadapter-testsupport": "^1.64.0",
"@vscode/vsce": "^2.22.0",
"conventional-changelog-conventionalcommits": "8.0.0",
"esbuild": "^0.14.29",
"eslint": "^8.52.0",
"eslint-config-prettier": "^9.0.0",
Expand All @@ -94,6 +94,7 @@
"mocha": "^10.2.0",
"nyc": "^15.1.0",
"prettier": "^3.0.3",
"semantic-release": "^24.1.2",
"shx": "^0.3.4",
"ts-mocha": "^10.0.0",
"typescript": "^4.6.3",
Expand Down
47 changes: 22 additions & 25 deletions src/common/appState.ts
Original file line number Diff line number Diff line change
@@ -1,33 +1,35 @@
import * as algosdk from 'algosdk';
import type {
AvmValue,
AvmKeyValue,
ApplicationInitialStates,
} from '@algorandfoundation/algokit-utils/algod-client';
import { hexToBytes } from '@algorandfoundation/algokit-utils/common';
import { ByteArrayMap } from './utils';

export class AppState {
globalState: ByteArrayMap<algosdk.modelsv2.AvmValue>;
localState: Map<string, ByteArrayMap<algosdk.modelsv2.AvmValue>>;
boxState: ByteArrayMap<algosdk.modelsv2.AvmValue>;
globalState: ByteArrayMap<AvmValue>;
localState: Map<string, ByteArrayMap<AvmValue>>;
boxState: ByteArrayMap<AvmValue>;

constructor() {
this.globalState = new ByteArrayMap<algosdk.modelsv2.AvmValue>();
this.localState = new Map<
string,
ByteArrayMap<algosdk.modelsv2.AvmValue>
>();
this.boxState = new ByteArrayMap<algosdk.modelsv2.AvmValue>();
this.globalState = new ByteArrayMap<AvmValue>();
this.localState = new Map<string, ByteArrayMap<AvmValue>>();
this.boxState = new ByteArrayMap<AvmValue>();
}

public globalStateArray(): algosdk.modelsv2.AvmKeyValue[] {
public globalStateArray(): AvmKeyValue[] {
return createAvmKvArray(this.globalState);
}

public localStateArray(account: string): algosdk.modelsv2.AvmKeyValue[] {
public localStateArray(account: string): AvmKeyValue[] {
const map = this.localState.get(account);
if (!map) {
return [];
}
return createAvmKvArray(map);
}

public boxStateArray(): algosdk.modelsv2.AvmKeyValue[] {
public boxStateArray(): AvmKeyValue[] {
return createAvmKvArray(this.boxState);
}

Expand All @@ -45,7 +47,7 @@ export class AppState {
}

public static fromAppInitialState(
initialState: algosdk.modelsv2.ApplicationInitialStates,
initialState: ApplicationInitialStates,
): AppState {
const state = new AppState();

Expand All @@ -56,7 +58,7 @@ export class AppState {
}

for (const appLocal of initialState.appLocals || []) {
const map = new ByteArrayMap<algosdk.modelsv2.AvmValue>();
const map = new ByteArrayMap<AvmValue>();
for (const { key, value } of appLocal.kvs) {
map.set(key, value);
}
Expand All @@ -73,16 +75,11 @@ export class AppState {
}
}

function createAvmKvArray(
map: ByteArrayMap<algosdk.modelsv2.AvmValue>,
): algosdk.modelsv2.AvmKeyValue[] {
function createAvmKvArray(map: ByteArrayMap<AvmValue>): AvmKeyValue[] {
return Array.from(map.entriesHex())
.sort()
.map(
([key, value]) =>
new algosdk.modelsv2.AvmKeyValue({
key: algosdk.hexToBytes(key),
value,
}),
);
.map(([key, value]) => ({
key: hexToBytes(key),
value,
}));
}
98 changes: 50 additions & 48 deletions src/common/debugSession.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,17 @@ import {
import { DebugProtocol } from '@vscode/debugprotocol';
import { AvmRuntime, IRuntimeBreakpoint } from './runtime';
import { Subject } from 'await-notify';
import * as algosdk from 'algosdk';
import type {
AvmValue,
AvmKeyValue,
} from '@algorandfoundation/algokit-utils/algod-client';
import {
bytesToHex,
bytesToBase64,
encodeAddress,
hexToBytes,
decodeAddress,
} from '@algorandfoundation/algokit-utils/common';
import { FileAccessor } from './fileAccessor';
import {
AvmDebuggingAssets,
Expand Down Expand Up @@ -541,12 +551,9 @@ export class AvmDebugSession extends DebugSession {
);
}
} else if (v.specificState === 'scratch') {
const expandedScratch: algosdk.modelsv2.AvmValue[] = [];
const expandedScratch: AvmValue[] = [];
for (let i = 0; i < 256; i++) {
expandedScratch.push(
programState.scratch.get(i) ||
new algosdk.modelsv2.AvmValue({ type: 2 }),
);
expandedScratch.push(programState.scratch.get(i) || { type: 2 });
}
if (args.filter !== 'named') {
variables = expandedScratch.map((value, index) =>
Expand Down Expand Up @@ -652,15 +659,13 @@ export class AvmDebugSession extends DebugSession {
v.scope instanceof PuyaScope
) {
const state = this.getProgramState(v.scope.frameIndex);
let toExpand: algosdk.modelsv2.AvmValue | undefined;
let toExpand: AvmValue | undefined;

if (v.scope instanceof ProgramStateScope) {
if (v.scope.specificState === 'stack') {
toExpand = state.stack[v.key as number];
} else if (v.scope.specificState === 'scratch') {
toExpand =
state.scratch.get(v.key as number) ||
new algosdk.modelsv2.AvmValue({ type: 2 });
toExpand = state.scratch.get(v.key as number) || { type: 2 };
}
} else if (v.scope instanceof PuyaScope) {
const variable = state.variables.find(([name]) => name === v.key);
Expand All @@ -677,16 +682,16 @@ export class AvmDebugSession extends DebugSession {
typeof v.key === 'string' &&
v.key.startsWith('0x')
) {
let toExpand: algosdk.modelsv2.AvmKeyValue;
let toExpand: AvmKeyValue;
const state = this._runtime.getAppState(v.scope.appID);
const keyHex = v.key.slice(2);
if (v.scope.scope === 'global') {
const value = state.globalState.getHex(keyHex);
if (value) {
toExpand = new algosdk.modelsv2.AvmKeyValue({
key: algosdk.hexToBytes(keyHex),
toExpand = {
key: hexToBytes(keyHex),
value,
});
};
} else {
throw new Error(`key "${v.key}" not found in global state`);
}
Expand All @@ -706,18 +711,18 @@ export class AvmDebugSession extends DebugSession {
`key "${v.key}" not found in local state for account "${v.scope.account}"`,
);
}
toExpand = new algosdk.modelsv2.AvmKeyValue({
key: algosdk.hexToBytes(keyHex),
toExpand = {
key: hexToBytes(keyHex),
value,
});
};
}
} else if (v.scope.scope === 'box') {
const value = state.boxState.getHex(keyHex);
if (value) {
toExpand = new algosdk.modelsv2.AvmKeyValue({
key: algosdk.hexToBytes(keyHex),
toExpand = {
key: hexToBytes(keyHex),
value,
});
};
} else {
throw new Error(`key "${v.key}" not found in box state`);
}
Expand Down Expand Up @@ -856,8 +861,7 @@ export class AvmDebugSession extends DebugSession {
if (0 <= index && index < 256) {
rv = this.convertAvmValue(
scopeWithFrame,
state.scratch.get(index) ||
new algosdk.modelsv2.AvmValue({ type: 2 }),
state.scratch.get(index) || { type: 2 },
index,
);
} else {
Expand All @@ -874,10 +878,10 @@ export class AvmDebugSession extends DebugSession {
const keyHex = key.slice(2);
const value = state.globalState.getHex(keyHex);
if (value) {
const kv = new algosdk.modelsv2.AvmKeyValue({
key: algosdk.hexToBytes(keyHex),
const kv = {
key: hexToBytes(keyHex),
value,
});
};
rv = this.convertAvmKeyValue(scope, kv);
} else {
reply = `key "${key}" not found in global state`;
Expand Down Expand Up @@ -906,10 +910,10 @@ export class AvmDebugSession extends DebugSession {
const keyHex = key.slice(2);
const value = accountState.getHex(keyHex);
if (value) {
const kv = new algosdk.modelsv2.AvmKeyValue({
key: algosdk.hexToBytes(keyHex),
const kv = {
key: hexToBytes(keyHex),
value,
});
};
rv = this.convertAvmKeyValue(scope, kv);
} else {
reply = `key "${key}" not found in local state for account "${scope.account}"`;
Expand All @@ -922,10 +926,10 @@ export class AvmDebugSession extends DebugSession {
const keyHex = key.slice(2);
const value = state.boxState.getHex(keyHex);
if (value) {
const kv = new algosdk.modelsv2.AvmKeyValue({
key: algosdk.hexToBytes(keyHex),
const kv = {
key: hexToBytes(keyHex),
value,
});
};
rv = this.convertAvmKeyValue(scope, kv);
} else {
reply = `key "${key}" not found in box state`;
Expand Down Expand Up @@ -1064,7 +1068,7 @@ export class AvmDebugSession extends DebugSession {

private convertAvmValue(
scope: AvmValueScope | PuyaScope,
avmValue: algosdk.modelsv2.AvmValue,
avmValue: AvmValue,
key: number | string,
overrideVariableReference?: boolean,
): DebugProtocol.Variable {
Expand Down Expand Up @@ -1118,7 +1122,7 @@ export class AvmDebugSession extends DebugSession {
}

private expandAvmValue(
avmValue: algosdk.modelsv2.AvmValue,
avmValue: AvmValue,
filter?: DebugProtocol.VariablesArguments['filter'],
): DebugProtocol.Variable[] {
// uint64 has no expanded variables
Expand All @@ -1133,14 +1137,14 @@ export class AvmDebugSession extends DebugSession {
values.push({
name: 'hex',
type: 'string',
value: algosdk.bytesToHex(bytes),
value: bytesToHex(bytes),
variablesReference: 0,
});

values.push({
name: 'base64',
type: 'string',
value: algosdk.bytesToBase64(bytes),
value: bytesToBase64(bytes),
variablesReference: 0,
});

Expand All @@ -1158,7 +1162,7 @@ export class AvmDebugSession extends DebugSession {
values.push({
name: 'address',
type: 'string',
value: algosdk.encodeAddress(bytes),
value: encodeAddress(bytes),
variablesReference: 0,
});
}
Expand Down Expand Up @@ -1187,10 +1191,9 @@ export class AvmDebugSession extends DebugSession {

private convertAvmKeyValue(
scope: AvmValueScope,
avmKeyValue: algosdk.modelsv2.AvmKeyValue,
avmKeyValue: AvmKeyValue,
): DebugProtocol.Variable {
const keyString =
'0x' + algosdk.bytesToHex(avmKeyValue.key || new Uint8Array());
const keyString = '0x' + bytesToHex(avmKeyValue.key || new Uint8Array());
const value = this.convertAvmValue(
scope,
avmKeyValue.value,
Expand All @@ -1204,15 +1207,14 @@ export class AvmDebugSession extends DebugSession {

private expandAvmKeyValue(
scope: AppSpecificStateScope,
avmKeyValue: algosdk.modelsv2.AvmKeyValue,
avmKeyValue: AvmKeyValue,
filter?: DebugProtocol.VariablesArguments['filter'],
): DebugProtocol.Variable[] {
if (typeof scope.property === 'undefined') {
if (filter === 'indexed') {
return [];
}
const keyString =
'0x' + algosdk.bytesToHex(avmKeyValue.key || new Uint8Array());
const keyString = '0x' + bytesToHex(avmKeyValue.key || new Uint8Array());
const keyScope = new AppSpecificStateScope({
scope: scope.scope,
appID: scope.appID,
Expand All @@ -1227,7 +1229,7 @@ export class AvmDebugSession extends DebugSession {
});
const keyVariable = this.convertAvmValue(
keyScope,
new algosdk.modelsv2.AvmValue({ type: 1, bytes: avmKeyValue.key }),
{ type: 1, bytes: avmKeyValue.key },
'',
false,
);
Expand Down Expand Up @@ -1270,21 +1272,21 @@ export class AvmDebugSession extends DebugSession {
}

if (scope.property === 'key') {
const avmKey = new algosdk.modelsv2.AvmValue({
const avmKey = {
type: 1,
bytes: avmKeyValue.key,
});
};
return this.expandAvmValue(avmKey, filter);
}

return this.expandAvmValue(avmKeyValue.value, filter);
}

private avmValueToString(avmValue: algosdk.modelsv2.AvmValue): string {
private avmValueToString(avmValue: AvmValue): string {
if (avmValue.type === 1) {
// byte array
const bytes = avmValue.bytes || new Uint8Array();
return '0x' + algosdk.bytesToHex(bytes);
return '0x' + bytesToHex(bytes);
}
// uint64
const uint = avmValue.uint || 0;
Expand Down Expand Up @@ -1436,7 +1438,7 @@ function evaluateNameToScope(name: string): [AvmValueScope, number | string] {
throw new Error(`Unexpected app property: ${property}`);
}
try {
algosdk.decodeAddress(appLocalMatches[2]); // ensure valid address
decodeAddress(appLocalMatches[2]); // ensure valid address
} catch {
throw new Error(`Invalid address: ${appLocalMatches[2]}:`);
}
Expand Down
Loading
Loading