Skip to content

Commit 2a4bc5b

Browse files
authored
Merge pull request #9 from algorandfoundation/feat-test-contracts
feat: add test contracts in typescript
2 parents 613ba33 + e5eeccf commit 2a4bc5b

28 files changed

+9342
-7958
lines changed

package-lock.json

Lines changed: 2891 additions & 1627 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,8 @@
6363
},
6464
"dependencies": {
6565
"@algorandfoundation/algokit-utils": "^6.2.1",
66-
"@algorandfoundation/algorand-typescript": "^0.0.1-alpha.15",
67-
"@algorandfoundation/puya-ts": "^1.0.0-alpha.14",
66+
"@algorandfoundation/algorand-typescript": "^0.0.1-alpha.16",
67+
"@algorandfoundation/puya-ts": "^1.0.0-alpha.24",
6868
"algosdk": "^2.9.0",
6969
"elliptic": "^6.5.7",
7070
"js-sha256": "^0.11.0",

src/impl/crypto.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { arc4, bytes, Bytes, gtxn, internal } from '@algorandfoundation/algorand-typescript'
1+
import { arc4, bytes, Bytes, Ecdsa, gtxn, internal, VrfVerify } from '@algorandfoundation/algorand-typescript'
22
import algosdk from 'algosdk'
33
import { ec } from 'elliptic'
44
import { sha256 as js_sha256 } from 'js-sha256'
@@ -68,7 +68,7 @@ export const ed25519verify = (
6868
}
6969

7070
export const ecdsaVerify = (
71-
v: internal.opTypes.Ecdsa,
71+
v: Ecdsa,
7272
a: internal.primitives.StubBytesCompat,
7373
b: internal.primitives.StubBytesCompat,
7474
c: internal.primitives.StubBytesCompat,
@@ -91,13 +91,13 @@ export const ecdsaVerify = (
9191
}
9292

9393
export const ecdsaPkRecover = (
94-
v: internal.opTypes.Ecdsa,
94+
v: Ecdsa,
9595
a: internal.primitives.StubBytesCompat,
9696
b: internal.primitives.StubUint64Compat,
9797
c: internal.primitives.StubBytesCompat,
9898
d: internal.primitives.StubBytesCompat,
9999
): readonly [bytes, bytes] => {
100-
if (v !== internal.opTypes.Ecdsa.Secp256k1) {
100+
if (v !== Ecdsa.Secp256k1) {
101101
internal.errors.internalError(`Unsupported ECDSA curve: ${v}`)
102102
}
103103
const dataBytes = internal.primitives.BytesCls.fromCompat(a)
@@ -117,7 +117,7 @@ export const ecdsaPkRecover = (
117117
return [Bytes(x), Bytes(y)]
118118
}
119119

120-
export const ecdsaPkDecompress = (v: internal.opTypes.Ecdsa, a: internal.primitives.StubBytesCompat): readonly [bytes, bytes] => {
120+
export const ecdsaPkDecompress = (v: Ecdsa, a: internal.primitives.StubBytesCompat): readonly [bytes, bytes] => {
121121
const bytesA = internal.primitives.BytesCls.fromCompat(a)
122122

123123
const ecdsa = new ec(curveMap[v])
@@ -130,7 +130,7 @@ export const ecdsaPkDecompress = (v: internal.opTypes.Ecdsa, a: internal.primiti
130130
}
131131

132132
export const vrfVerify = (
133-
_s: internal.opTypes.VrfVerify,
133+
_s: VrfVerify,
134134
_a: internal.primitives.StubBytesCompat,
135135
_b: internal.primitives.StubBytesCompat,
136136
_c: internal.primitives.StubBytesCompat,
@@ -145,6 +145,6 @@ export const EllipticCurve = new Proxy({} as internal.opTypes.EllipticCurveType,
145145
})
146146

147147
const curveMap = {
148-
[internal.opTypes.Ecdsa.Secp256k1]: 'secp256k1',
149-
[internal.opTypes.Ecdsa.Secp256r1]: 'p256',
148+
[Ecdsa.Secp256k1]: 'secp256k1',
149+
[Ecdsa.Secp256r1]: 'p256',
150150
}

src/impl/pure.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { biguint, Bytes, bytes, internal, Uint64, uint64 } from '@algorandfoundation/algorand-typescript'
1+
import { Base64, biguint, Bytes, bytes, internal, Uint64, uint64 } from '@algorandfoundation/algorand-typescript'
22
import { BITS_IN_BYTE, MAX_BYTES_SIZE, MAX_UINT64, MAX_UINT8, UINT64_SIZE } from '../constants'
33
import { notImplementedError, testInvariant } from '../errors'
44
import { asBigUint, asBytes, asMaybeBytesCls, asMaybeUint64Cls, asUint64Cls, binaryStringToBytes } from '../util'
@@ -10,8 +10,8 @@ export const addw = (a: internal.primitives.StubUint64Compat, b: internal.primit
1010
return toUint128(sum)
1111
}
1212

13-
export const base64Decode = (e: internal.opTypes.Base64, a: internal.primitives.StubBytesCompat): bytes => {
14-
const encoding = e === internal.opTypes.Base64.StdEncoding ? 'base64' : 'base64url'
13+
export const base64Decode = (e: Base64, a: internal.primitives.StubBytesCompat): bytes => {
14+
const encoding = e === Base64.StdEncoding ? 'base64' : 'base64url'
1515
const bytesValue = internal.primitives.BytesCls.fromCompat(a)
1616
const stringValue = bytesValue.toString()
1717

src/test-transformer/node-factory.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,16 @@ export const nodeFactory = {
2828
[left, right, factory.createStringLiteral(op)],
2929
)
3030
},
31+
augmentedAssignmentBinaryOp(left: ts.Expression, right: ts.Expression, op: string) {
32+
return factory.createAssignment(
33+
left,
34+
factory.createCallExpression(
35+
factory.createPropertyAccessExpression(factory.createIdentifier('runtimeHelpers'), factory.createIdentifier('binaryOp')),
36+
undefined,
37+
[left, right, factory.createStringLiteral(op.replace('=', ''))],
38+
),
39+
)
40+
},
3141

3242
prefixUnaryOp(operand: ts.Expression, op: string) {
3343
return factory.createCallExpression(

src/test-transformer/supported-binary-op-string.ts

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,6 @@ export function supportedBinaryOpString(x: BinaryOperator): string | undefined {
4040
case ts.SyntaxKind.AmpersandAmpersandEqualsToken:
4141
case ts.SyntaxKind.AmpersandAmpersandToken:
4242
case ts.SyntaxKind.AmpersandEqualsToken:
43-
case ts.SyntaxKind.AsteriskAsteriskEqualsToken:
44-
case ts.SyntaxKind.AsteriskEqualsToken:
4543
case ts.SyntaxKind.BarBarEqualsToken:
4644
case ts.SyntaxKind.BarBarToken:
4745
case ts.SyntaxKind.BarEqualsToken:
@@ -52,11 +50,7 @@ export function supportedBinaryOpString(x: BinaryOperator): string | undefined {
5250
case ts.SyntaxKind.ExclamationEqualsToken:
5351
case ts.SyntaxKind.InKeyword:
5452
case ts.SyntaxKind.InstanceOfKeyword:
55-
case ts.SyntaxKind.PercentEqualsToken:
56-
case ts.SyntaxKind.PlusEqualsToken:
5753
case ts.SyntaxKind.QuestionQuestionEqualsToken:
58-
case ts.SyntaxKind.MinusEqualsToken:
59-
case ts.SyntaxKind.SlashEqualsToken:
6054
case ts.SyntaxKind.QuestionQuestionToken:
6155
case ts.SyntaxKind.GreaterThanGreaterThanEqualsToken:
6256
case ts.SyntaxKind.LessThanLessThanEqualsToken:
@@ -66,6 +60,25 @@ export function supportedBinaryOpString(x: BinaryOperator): string | undefined {
6660
}
6761
}
6862

63+
export function supportedAugmentedAssignmentBinaryOpString(x: BinaryOperator): string | undefined {
64+
switch (x) {
65+
case ts.SyntaxKind.PlusEqualsToken:
66+
return '+='
67+
case ts.SyntaxKind.MinusEqualsToken:
68+
return '-='
69+
case ts.SyntaxKind.SlashEqualsToken:
70+
return '/='
71+
case ts.SyntaxKind.AsteriskEqualsToken:
72+
return '*='
73+
case ts.SyntaxKind.AsteriskAsteriskEqualsToken:
74+
return '**='
75+
case ts.SyntaxKind.PercentEqualsToken:
76+
return '%='
77+
default:
78+
return undefined
79+
}
80+
}
81+
6982
export function supportedPrefixUnaryOpString(x: PrefixUnaryOperator): string | undefined {
7083
switch (x) {
7184
case ts.SyntaxKind.TildeToken:

src/test-transformer/visitors.ts

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,11 @@ import type { TypeInfo } from '../encoders'
44
import { DeliberateAny } from '../typescript-helpers'
55
import { TransformerConfig } from './index'
66
import { nodeFactory } from './node-factory'
7-
import { supportedBinaryOpString, supportedPrefixUnaryOpString } from './supported-binary-op-string'
7+
import {
8+
supportedAugmentedAssignmentBinaryOpString,
9+
supportedBinaryOpString,
10+
supportedPrefixUnaryOpString,
11+
} from './supported-binary-op-string'
812

913
const { factory } = ts
1014

@@ -34,7 +38,7 @@ export class SourceFileVisitor {
3438
}
3539
},
3640
sourceLocation(node: ts.Node): SourceLocation {
37-
return SourceLocation.fromNode(sourceFile, node, program.getCurrentDirectory())
41+
return SourceLocation.fromNode(node, program.getCurrentDirectory())
3842
},
3943
}
4044
}
@@ -81,9 +85,13 @@ class FunctionOrMethodVisitor {
8185
}
8286

8387
if (ts.isBinaryExpression(node)) {
84-
const tokenText = supportedBinaryOpString(node.operatorToken.kind)
85-
if (tokenText) {
86-
return nodeFactory.binaryOp(node.left, node.right, tokenText)
88+
const opTokenText = supportedBinaryOpString(node.operatorToken.kind)
89+
if (opTokenText) {
90+
return nodeFactory.binaryOp(node.left, node.right, opTokenText)
91+
}
92+
const augmentedAssignmentOpTokenText = supportedAugmentedAssignmentBinaryOpString(node.operatorToken.kind)
93+
if (augmentedAssignmentOpTokenText) {
94+
return nodeFactory.augmentedAssignmentBinaryOp(node.left, node.right, augmentedAssignmentOpTokenText)
8795
}
8896
}
8997
if (ts.isPrefixUnaryExpression(node)) {
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
import { arc4, bytes, Ecdsa, ensureBudget, op, OpUpFeeSource, uint64, VrfVerify } from '@algorandfoundation/algorand-typescript'
2+
3+
export class CryptoOpsContract extends arc4.Contract {
4+
@arc4.abimethod()
5+
public verify_sha256(a: bytes, pad_size: uint64): bytes {
6+
const paddedA = op.bzero(pad_size).concat(a)
7+
const result = op.sha256(paddedA)
8+
return result
9+
}
10+
11+
@arc4.abimethod()
12+
public verify_sha3_256(a: bytes, pad_size: uint64): bytes {
13+
const paddedA = op.bzero(pad_size).concat(a)
14+
const result = op.sha3_256(paddedA)
15+
return result
16+
}
17+
18+
@arc4.abimethod()
19+
public verify_keccak_256(a: bytes, pad_size: uint64): bytes {
20+
const paddedA = op.bzero(pad_size).concat(a)
21+
const result = op.keccak256(paddedA)
22+
return result
23+
}
24+
25+
@arc4.abimethod()
26+
public verify_sha512_256(a: bytes, pad_size: uint64): bytes {
27+
const paddedA = op.bzero(pad_size).concat(a)
28+
const result = op.sha512_256(paddedA)
29+
return result
30+
}
31+
32+
// TODO: return arc4.Bool to match python version when arc4 types are available
33+
@arc4.abimethod()
34+
public verify_ed25519verify(a: bytes, b: bytes, c: bytes): boolean {
35+
ensureBudget(1900, OpUpFeeSource.GroupCredit)
36+
const result = op.ed25519verify(a, b, c)
37+
return result
38+
}
39+
40+
// TODO: return arc4.Bool to match python version when arc4 types are available
41+
@arc4.abimethod()
42+
public verify_ed25519verify_bare(a: bytes, b: bytes, c: bytes): boolean {
43+
ensureBudget(1900, OpUpFeeSource.GroupCredit)
44+
const result = op.ed25519verifyBare(a, b, c)
45+
return result
46+
}
47+
48+
@arc4.abimethod()
49+
public verify_ecdsa_verify_k1(a: bytes, b: bytes, c: bytes, d: bytes, e: bytes): boolean {
50+
ensureBudget(3000, OpUpFeeSource.GroupCredit)
51+
const result_k1 = op.ecdsaVerify(Ecdsa.Secp256k1, a, b, c, d, e)
52+
return result_k1
53+
}
54+
55+
@arc4.abimethod()
56+
public verify_ecdsa_verify_r1(a: bytes, b: bytes, c: bytes, d: bytes, e: bytes): boolean {
57+
ensureBudget(3000, OpUpFeeSource.GroupCredit)
58+
const result_r1 = op.ecdsaVerify(Ecdsa.Secp256r1, a, b, c, d, e)
59+
return result_r1
60+
}
61+
62+
@arc4.abimethod()
63+
public verify_ecdsa_recover_k1(a: bytes, b: uint64, c: bytes, d: bytes): readonly [bytes, bytes] {
64+
ensureBudget(3000, OpUpFeeSource.GroupCredit)
65+
return op.ecdsaPkRecover(Ecdsa.Secp256k1, a, b, c, d)
66+
}
67+
68+
@arc4.abimethod()
69+
public verify_ecdsa_recover_r1(a: bytes, b: uint64, c: bytes, d: bytes): readonly [bytes, bytes] {
70+
/**
71+
* Must fail, AVM does not support Secp256r1 for recover
72+
*/
73+
ensureBudget(3000, OpUpFeeSource.GroupCredit)
74+
return op.ecdsaPkRecover(Ecdsa.Secp256r1, a, b, c, d)
75+
}
76+
77+
@arc4.abimethod()
78+
public verify_ecdsa_decompress_k1(a: bytes): readonly [bytes, bytes] {
79+
ensureBudget(700, OpUpFeeSource.GroupCredit)
80+
return op.ecdsaPkDecompress(Ecdsa.Secp256k1, a)
81+
}
82+
83+
@arc4.abimethod()
84+
public verify_ecdsa_decompress_r1(a: bytes): readonly [bytes, bytes] {
85+
ensureBudget(700, OpUpFeeSource.GroupCredit)
86+
return op.ecdsaPkDecompress(Ecdsa.Secp256r1, a)
87+
}
88+
89+
@arc4.abimethod()
90+
public verify_vrf_verify(a: bytes, b: bytes, c: bytes): readonly [bytes, boolean] {
91+
ensureBudget(5700, OpUpFeeSource.GroupCredit)
92+
const result = op.vrfVerify(VrfVerify.VrfAlgorand, a, b, c)
93+
return result
94+
}
95+
}

0 commit comments

Comments
 (0)