Skip to content

Commit ac2437b

Browse files
committed
refactor: add tests dependent upon arc4 types
1 parent c9061f6 commit ac2437b

File tree

66 files changed

+11592
-2323
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

66 files changed

+11592
-2323
lines changed

src/impl/app-global.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { Application, Bytes, bytes, internal, Uint64, uint64 } from '@algorandfoundation/algorand-typescript'
22
import { lazyContext } from '../context-helpers/internal-context'
3-
import { asBytes } from '../util'
3+
import { asBytes, toBytes } from '../util'
44
import { getApp } from './app-params'
55

66
export const AppGlobal: internal.opTypes.AppGlobalType = {
@@ -22,7 +22,7 @@ export const AppGlobal: internal.opTypes.AppGlobalType = {
2222
if (!exists) {
2323
return [Bytes(), false]
2424
}
25-
return [state!.value as bytes, exists]
25+
return [toBytes(state!.value), exists]
2626
},
2727
getExUint64(a: Application | internal.primitives.StubUint64Compat, b: internal.primitives.StubBytesCompat): readonly [uint64, boolean] {
2828
const app = getApp(a)

src/impl/app-local.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { Account, Application, Bytes, bytes, internal, Uint64, uint64 } from '@algorandfoundation/algorand-typescript'
22
import { lazyContext } from '../context-helpers/internal-context'
3-
import { asBytes } from '../util'
3+
import { asBytes, toBytes } from '../util'
44
import { getAccount } from './acct-params'
55
import { getApp } from './app-params'
66

@@ -32,7 +32,7 @@ export const AppLocal: internal.opTypes.AppLocalType = {
3232
if (!exists) {
3333
return [Bytes(), false]
3434
}
35-
return [state!.value as bytes, exists]
35+
return [toBytes(state!.value), exists]
3636
},
3737
getExUint64: function (
3838
a: Account | internal.primitives.StubUint64Compat,

src/set-up.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { internal } from '@algorandfoundation/algorand-typescript'
2+
import { Address } from '@algorandfoundation/algorand-typescript/arc4'
23
import { encodingUtil } from '@algorandfoundation/puya-ts'
34
import { AccountCls } from './impl/account'
45

@@ -77,6 +78,33 @@ function addEqualityTesters(expectObj: ExpectObj) {
7778
// Defer to other testers
7879
return undefined
7980
},
81+
function AddressIsAccountStr(this: TesterContext, subject, test, customTesters): boolean | undefined {
82+
if (subject instanceof Address) {
83+
const testValue = typeof test === 'string' ? encodingUtil.base32ToUint8Array(test).slice(0, 32) : undefined
84+
if (testValue !== undefined) return this.equals(subject.native.bytes, testValue, customTesters)
85+
return undefined
86+
}
87+
// Defer to other testers
88+
return undefined
89+
},
90+
function AddressIsAccountBytes(this: TesterContext, subject, test, customTesters): boolean | undefined {
91+
if (subject instanceof Address) {
92+
const testValue = test instanceof internal.primitives.BytesCls ? test.asUint8Array().slice(0, 32) : undefined
93+
if (testValue !== undefined) return this.equals(subject.native.bytes, testValue, customTesters)
94+
return undefined
95+
}
96+
// Defer to other testers
97+
return undefined
98+
},
99+
function AddressIsAccount(this: TesterContext, subject, test, customTesters): boolean | undefined {
100+
if (subject instanceof Address) {
101+
const testValue = test instanceof AccountCls ? test.bytes : undefined
102+
if (testValue !== undefined) return this.equals(subject.native.bytes, testValue, customTesters)
103+
return undefined
104+
}
105+
// Defer to other testers
106+
return undefined
107+
},
80108
])
81109
}
82110

src/subcontexts/contract-context.ts

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import {
1818
} from '../impl/transactions'
1919
import { getGenericTypeInfo } from '../runtime-helpers'
2020
import { DeliberateAny, IConstructor } from '../typescript-helpers'
21-
import { asUint64Cls } from '../util'
21+
import { toBytes } from '../util'
2222

2323
type StateTotals = Pick<Application, 'globalNumBytes' | 'globalNumUint' | 'localNumBytes' | 'localNumUint'>
2424

@@ -76,18 +76,17 @@ const extractArraysFromArgs = (app: Application, args: DeliberateAny[]) => {
7676
const assets: Asset[] = []
7777
const appArgs: bytes[] = []
7878

79-
// TODO: replace `asUint64Cls(accounts.length).toBytes().asAlgoTs()` with `arc4.Uint8(account.length).toBytes().asAlgoTs()`
8079
for (const arg of args) {
8180
if (isTransaction(arg)) {
8281
transactions.push(arg)
8382
} else if (arg instanceof AccountCls) {
84-
appArgs.push(asUint64Cls(accounts.length).toBytes().asAlgoTs())
83+
appArgs.push(toBytes(accounts.length))
8584
accounts.push(arg as Account)
8685
} else if (arg instanceof ApplicationCls) {
87-
appArgs.push(asUint64Cls(apps.length).toBytes().asAlgoTs())
86+
appArgs.push(toBytes(apps.length))
8887
apps.push(arg as Application)
8988
} else if (arg instanceof AssetCls) {
90-
appArgs.push(asUint64Cls(assets.length).toBytes().asAlgoTs())
89+
appArgs.push(toBytes(assets.length))
9190
assets.push(arg as Asset)
9291
}
9392
}

src/test-execution-context.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,13 @@ export class TestExecutionContext implements internal.ExecutionContext {
2828
#valueGenerator: ValueGenerator
2929
#defaultSender: Account
3030

31-
constructor() {
31+
constructor(defaultSenderAddress?: bytes) {
3232
internal.ctxMgr.instance = this
3333
this.#contractContext = new ContractContext()
3434
this.#ledgerContext = new LedgerContext()
3535
this.#txnContext = new TransactionContext()
3636
this.#valueGenerator = new ValueGenerator()
37-
this.#defaultSender = Account(Bytes.fromBase32(algosdk.generateAccount().addr))
37+
this.#defaultSender = Account(defaultSenderAddress ?? Bytes.fromBase32(algosdk.generateAccount().addr))
3838
}
3939

4040
account(address?: bytes): Account {

src/util.ts

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { Bytes, bytes, internal } from '@algorandfoundation/algorand-typescript'
2+
import { ARC4Encoded } from '@algorandfoundation/algorand-typescript/arc4'
23
import { randomBytes } from 'crypto'
34
import { BITS_IN_BYTE, MAX_BYTES_SIZE, MAX_UINT512, MAX_UINT8, UINT512_SIZE } from './constants'
45
import { BytesBackedCls, Uint64BackedCls } from './impl/base'
@@ -45,7 +46,6 @@ export const asBytes = (val: internal.primitives.StubBytesCompat | Uint8Array) =
4546

4647
export const asUint8Array = (val: internal.primitives.StubBytesCompat | Uint8Array) => asBytesCls(val).asUint8Array()
4748

48-
//TODO: handle arc4 types, bytes backed types
4949
export const toBytes = (val: unknown): bytes => {
5050
const uint64Val = asMaybeUint64Cls(val)
5151
if (uint64Val !== undefined) {
@@ -66,17 +66,13 @@ export const toBytes = (val: unknown): bytes => {
6666
return asUint64Cls(val.uint64).toBytes().asAlgoTs()
6767
}
6868
if (Array.isArray(val)) {
69-
// This hack handles tuples/arrays of uint64 only
7069
return val.reduce((acc: bytes, cur: unknown) => {
71-
const uint64Val = asMaybeUint64Cls(cur)
72-
if (!uint64Val) {
73-
// TODO: support ABI tuple encoding
74-
// internal.errors.internalError(`ABI tuple encoding not supported: ${nameOfType(val)}`)
75-
return acc.concat(Bytes())
76-
}
7770
return acc.concat(toBytes(cur))
7871
}, Bytes())
7972
}
73+
if (val instanceof ARC4Encoded) {
74+
return val.bytes
75+
}
8076
internal.errors.internalError(`Invalid type for bytes: ${nameOfType(val)}`)
8177
}
8278

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,21 @@
1-
import { arc4, assert, Box, Bytes, op, TransactionType, uint64, Uint64 } from '@algorandfoundation/algorand-typescript'
2-
3-
// type X = [a: uint64, b: string, c: bytes]
4-
// type Y = { a: uint64; b: string; c: bytes }
5-
// type Z = { x: X; y: Y }
1+
import { arc4, assert, Box, Bytes, op, TransactionType } from '@algorandfoundation/algorand-typescript'
2+
import { Tuple, UintN64 } from '@algorandfoundation/algorand-typescript/arc4'
63

74
export class BoxContract extends arc4.Contract {
85
oca = Box<arc4.OnCompleteAction>({ key: Bytes('oca') })
96
txn = Box<TransactionType>({ key: Bytes('txn') })
107

11-
// a = Box<X>({ key: Bytes('a') })
12-
// b = Box<Y>({ key: Bytes('b') })
13-
// c = Box<Z>({ key: Bytes('c') })
14-
// d = Box<Z[]>({ key: Bytes('d') })
15-
168
@arc4.abimethod()
179
public storeEnums(): void {
1810
this.oca.value = arc4.OnCompleteAction.OptIn
1911
this.txn.value = TransactionType.ApplicationCall
2012
}
2113

2214
@arc4.abimethod()
23-
public read_enums(): readonly [uint64, uint64] {
15+
public read_enums(): Tuple<[UintN64, UintN64]> {
2416
assert(op.Box.get(Bytes('oca'))[0] === op.itob(this.oca.value))
2517
assert(op.Box.get(Bytes('txn'))[0] === op.itob(this.txn.value))
2618

27-
return [Uint64(this.oca.value), Uint64(this.txn.value)]
28-
// TODO: use arc4 types when available
29-
// return arc4.Tuple((arc4.UInt64(this.oca.value), arc4.UInt64(this.txn.value)))
19+
return new Tuple(new UintN64(this.oca.value), new UintN64(this.txn.value))
3020
}
3121
}

tests/artifacts/crypto-ops/contract.algo.ts

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { arc4, bytes, Ecdsa, ensureBudget, op, OpUpFeeSource, uint64, VrfVerify } from '@algorandfoundation/algorand-typescript'
2+
import { Bool } from '@algorandfoundation/algorand-typescript/arc4'
23

34
export class CryptoOpsContract extends arc4.Contract {
45
@arc4.abimethod()
@@ -29,20 +30,18 @@ export class CryptoOpsContract extends arc4.Contract {
2930
return result
3031
}
3132

32-
// TODO: return arc4.Bool to match python version when arc4 types are available
3333
@arc4.abimethod()
34-
public verify_ed25519verify(a: bytes, b: bytes, c: bytes): boolean {
34+
public verify_ed25519verify(a: bytes, b: bytes, c: bytes): Bool {
3535
ensureBudget(1900, OpUpFeeSource.GroupCredit)
3636
const result = op.ed25519verify(a, b, c)
37-
return result
37+
return new Bool(result)
3838
}
3939

40-
// TODO: return arc4.Bool to match python version when arc4 types are available
4140
@arc4.abimethod()
42-
public verify_ed25519verify_bare(a: bytes, b: bytes, c: bytes): boolean {
41+
public verify_ed25519verify_bare(a: bytes, b: bytes, c: bytes): Bool {
4342
ensureBudget(1900, OpUpFeeSource.GroupCredit)
4443
const result = op.ed25519verifyBare(a, b, c)
45-
return result
44+
return new Bool(result)
4645
}
4746

4847
@arc4.abimethod()

tests/artifacts/primitive-ops/contract.algo.ts

Lines changed: 37 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,18 @@
1-
import { arc4, biguint, BigUint, Bytes, bytes, op, uint64 } from '@algorandfoundation/algorand-typescript'
1+
import { arc4, biguint, BigUint, Bytes, bytes, log, op, uint64 } from '@algorandfoundation/algorand-typescript'
2+
import {
3+
Bool,
4+
DynamicArray,
5+
interpretAsArc4,
6+
StaticArray,
7+
Str,
8+
Tuple,
9+
UFixedNxM,
10+
UintN,
11+
UintN16,
12+
UintN32,
13+
UintN64,
14+
UintN8,
15+
} from '@algorandfoundation/algorand-typescript/arc4'
216

317
export class PrimitiveOpsContract extends arc4.Contract {
418
@arc4.abimethod()
@@ -390,27 +404,26 @@ export class PrimitiveOpsContract extends arc4.Contract {
390404
return result
391405
}
392406

393-
// TODO: uncomment when arc4 types are available
394-
// @arc4.abimethod
395-
// public verify_log( # noqa: PLR0913
396-
// self,
397-
// a: String,
398-
// b: uint64,
399-
// c: bytes,
400-
// d: bytes,
401-
// e: arc4.boolean,
402-
// f: arc4.String,
403-
// g: arc4.UIntN[typing.Literal[64]],
404-
// h: arc4.BigUIntN[typing.Literal[256]],
405-
// i: arc4.UFixedNxM[typing.Literal[32], typing.Literal[8]],
406-
// j: arc4.BigUFixedNxM[typing.Literal[256], typing.Literal[16]],
407-
// k: bytes,
408-
// m: bytes,
409-
// n: bytes,
410-
// ) : None:
411-
// d_biguint = BigUint(d)
412-
// arc4_k = arc4.StaticArray[arc4.UInt8, typing.Literal[3]].from_bytes(k)
413-
// arc4_m = arc4.DynamicArray[arc4.UInt16].from_bytes(m)
414-
// arc4_n = arc4.Tuple[arc4.UInt32, arc4.uint64, arc4.String].from_bytes(n)
415-
// log(a, b, c, d_biguint, e, f, g, h, i, j, arc4_k, arc4_m, arc4_n, sep="-")
407+
@arc4.abimethod()
408+
public verify_log(
409+
a: string,
410+
b: uint64,
411+
c: bytes,
412+
d: bytes,
413+
e: Bool,
414+
f: Str,
415+
g: UintN<64>,
416+
h: UintN<256>,
417+
i: UFixedNxM<32, 8>,
418+
j: UFixedNxM<256, 16>,
419+
k: bytes,
420+
m: bytes,
421+
n: bytes,
422+
) {
423+
const d_biguint = BigUint(d)
424+
const arc4_k = interpretAsArc4<StaticArray<UintN8, 3>>(k)
425+
const arc4_m = interpretAsArc4<DynamicArray<UintN16>>(m)
426+
const arc4_n = interpretAsArc4<Tuple<[UintN32, UintN64, Str]>>(n)
427+
log(a, b, c, d_biguint, e, f, g, h, i, j, arc4_k, arc4_m, arc4_n)
428+
}
416429
}

0 commit comments

Comments
 (0)