11import type { biguint , bytes , uint64 } from '@algorandfoundation/algorand-typescript'
22import { Bytes } from '@algorandfoundation/algorand-typescript'
3- import type { Address , StaticArray , StaticBytes , UFixedNxM , UintN64 } from '@algorandfoundation/algorand-typescript/arc4'
3+ import type { StaticBytes , UFixedNxM } from '@algorandfoundation/algorand-typescript/arc4'
44import {
5+ Address ,
56 arc4EncodedLength ,
67 Bool ,
78 decodeArc4 ,
9+ DynamicArray ,
810 DynamicBytes ,
911 encodeArc4 ,
12+ StaticArray ,
1013 Str ,
1114 Struct ,
1215 Tuple ,
1316 UintN ,
17+ UintN64 ,
1418} from '@algorandfoundation/algorand-typescript/arc4'
19+ import { itob } from '@algorandfoundation/algorand-typescript/op'
20+ import { encodingUtil } from '@algorandfoundation/puya-ts'
1521import { describe , expect , test } from 'vitest'
1622import { MAX_UINT128 } from '../../src/constants'
1723import type { StubBytesCompat } from '../../src/impl/primitives'
@@ -30,6 +36,7 @@ const abiUint512 = new UintN<512>(MAX_UINT128)
3036const abiBool = new Bool ( true )
3137const abiBytes = new DynamicBytes ( Bytes ( 'hello' ) )
3238
39+ type TestObj = { a : UintN64 ; b : DynamicBytes }
3340class Swapped1 extends Struct < {
3441 b : UintN < 64 >
3542 c : Bool
@@ -40,14 +47,17 @@ class Swapped1 extends Struct<{
4047const testData = [
4148 {
4249 nativeValues ( ) {
43- return [ nativeNumber , nativeNumber , nativeBigInt , nativeBytes ]
50+ return [ nativeNumber , nativeNumber , nativeBigInt , nativeBytes ] as readonly [ uint64 , uint64 , biguint , bytes ]
4451 } ,
4552 abiValues ( ) {
4653 return [ abiUint64 , abiUint64 , abiUint512 , abiBytes ] as readonly [ UintN < 64 > , UintN < 64 > , UintN < 512 > , DynamicBytes ]
4754 } ,
4855 arc4Value ( ) {
4956 return new Tuple < [ UintN < 64 > , UintN < 64 > , UintN < 512 > , DynamicBytes ] > ( abiUint64 , abiUint64 , abiUint512 , abiBytes )
5057 } ,
58+ encode ( ) {
59+ return encodeArc4 ( this . nativeValues ( ) )
60+ } ,
5161 decode ( value : StubBytesCompat ) {
5262 return decodeArc4 < [ uint64 , uint64 , biguint , bytes ] > ( asBytes ( value ) )
5363 } ,
@@ -58,6 +68,19 @@ const testData = [
5868 [ nativeBool , [ nativeString , nativeBool ] ] ,
5969 [ nativeNumber , nativeNumber ] ,
6070 [ nativeBigInt , nativeBytes , { b : nativeNumber , c : nativeBool , d : nativeString , a : [ nativeNumber , nativeBool , nativeBool ] } ] ,
71+ ] as readonly [
72+ [ boolean , [ string , boolean ] ] ,
73+ [ uint64 , uint64 ] ,
74+ [
75+ biguint ,
76+ bytes ,
77+ {
78+ b : uint64
79+ c : boolean
80+ d : string
81+ a : [ uint64 , boolean , boolean ]
82+ } ,
83+ ] ,
6184 ]
6285 } ,
6386 abiValues ( ) {
@@ -76,6 +99,9 @@ const testData = [
7699 ...this . abiValues ( ) ,
77100 )
78101 } ,
102+ encode ( ) {
103+ return encodeArc4 ( this . nativeValues ( ) )
104+ } ,
79105 decode ( value : StubBytesCompat ) {
80106 return decodeArc4 <
81107 [
@@ -105,6 +131,9 @@ const testData = [
105131 arc4Value ( ) {
106132 return new Swapped1 ( this . abiValues ( ) )
107133 } ,
134+ encode ( ) {
135+ return encodeArc4 ( this . nativeValues ( ) )
136+ } ,
108137 decode ( value : StubBytesCompat ) {
109138 return decodeArc4 < { b : uint64 ; c : boolean ; d : string ; a : [ uint64 , boolean , boolean ] } > ( asBytes ( value ) )
110139 } ,
@@ -120,17 +149,67 @@ describe('decodeArc4', () => {
120149
121150 compareNativeValues ( result , nativeValues )
122151 } )
152+ test ( 'should be able to decode arrays' , ( ) => {
153+ const a = 234234
154+ const aBytes = asBytes ( encodingUtil . bigIntToUint8Array ( 234234n , 8 ) )
155+ const b = true
156+ const bBytes = asBytes ( encodingUtil . bigIntToUint8Array ( 128n , 1 ) )
157+ const c = 340943934n
158+ const cBytes = asBytes ( encodingUtil . bigIntToUint8Array ( 340943934n , 512 / 8 ) )
159+ const d = 'hello world'
160+ const dBytes = asBytes (
161+ new Uint8Array ( [
162+ ...encodingUtil . bigIntToUint8Array ( BigInt ( 'hello world' . length ) , 2 ) ,
163+ ...encodingUtil . utf8ToUint8Array ( 'hello world' ) ,
164+ ] ) ,
165+ )
166+ const e = { a : 50n , b : new Uint8Array ( [ 1 , 2 , 3 , 4 , 5 ] ) }
167+ const eBytes = asBytes ( new Uint8Array ( [ ...encodingUtil . bigIntToUint8Array ( 50n , 8 ) , 0 , 10 , 0 , 5 , 1 , 2 , 3 , 4 , 5 ] ) )
168+ const f = new Address ( Bytes . fromHex ( `${ '00' . repeat ( 31 ) } ff` ) )
169+ const fBytes = Bytes . fromHex ( `${ '00' . repeat ( 31 ) } ff` )
170+ expect ( decodeArc4 < uint64 > ( aBytes ) ) . toEqual ( a )
171+ expect ( decodeArc4 < boolean > ( bBytes ) ) . toEqual ( b )
172+ expect ( decodeArc4 < biguint > ( cBytes ) ) . toEqual ( c )
173+ expect ( decodeArc4 < string > ( dBytes ) ) . toEqual ( d )
174+ expect ( decodeArc4 < TestObj > ( eBytes ) ) . toEqual ( e )
175+
176+ const lenPrefix = itob ( 1 ) . slice ( 6 , 8 )
177+ const offsetHeader = itob ( 2 ) . slice ( 6 , 8 )
178+ expect ( decodeArc4 < uint64 [ ] > ( lenPrefix . concat ( aBytes ) ) ) . toEqual ( [ a ] )
179+ expect ( decodeArc4 < boolean [ ] > ( lenPrefix . concat ( bBytes ) ) ) . toEqual ( [ b ] )
180+ expect ( decodeArc4 < biguint [ ] > ( lenPrefix . concat ( cBytes ) ) ) . toEqual ( [ c ] )
181+ expect ( decodeArc4 < string [ ] > ( Bytes `${ lenPrefix } ${ offsetHeader } ${ dBytes } ` ) ) . toEqual ( [ d ] )
182+ expect ( decodeArc4 < TestObj [ ] > ( Bytes `${ lenPrefix } ${ offsetHeader } ${ eBytes } ` ) ) . toEqual ( [ e ] )
183+ expect ( JSON . stringify ( decodeArc4 < Address [ ] > ( Bytes `${ lenPrefix } ${ fBytes } ` ) ) ) . toEqual ( JSON . stringify ( [ f ] ) )
184+ } )
123185} )
124186
125187describe ( 'encodeArc4' , ( ) => {
126188 test . each ( testData ) ( 'should encode native values' , ( data ) => {
127- const nativeValues = data . nativeValues ( )
128189 const arc4Value = data . arc4Value ( )
129190
130- const result = encodeArc4 ( nativeValues )
191+ const result = data . encode ( )
131192
132193 expect ( result ) . toEqual ( arc4Value . bytes )
133194 } )
195+ test ( 'should be able to encode arrays' , ( ) => {
196+ const address = new Address ( Bytes . fromHex ( `${ '00' . repeat ( 31 ) } ff` ) )
197+ expect ( encodeArc4 ( address ) ) . toEqual ( address . bytes )
198+
199+ expect ( encodeArc4 ( [ nativeNumber ] ) ) . toEqual ( new StaticArray ( new UintN64 ( nativeNumber ) ) . bytes )
200+ expect ( encodeArc4 ( [ nativeBool ] ) ) . toEqual ( new StaticArray ( new Bool ( nativeBool ) ) . bytes )
201+ expect ( encodeArc4 ( [ nativeBigInt ] ) ) . toEqual ( new StaticArray ( new UintN < 512 > ( nativeBigInt ) ) . bytes )
202+ expect ( encodeArc4 ( [ nativeBytes ] ) ) . toEqual ( new StaticArray ( new DynamicBytes ( nativeBytes ) ) . bytes )
203+ expect ( encodeArc4 ( [ nativeString ] ) ) . toEqual ( new StaticArray ( new Str ( nativeString ) ) . bytes )
204+ expect ( encodeArc4 ( [ address ] ) ) . toEqual ( new StaticArray ( address ) . bytes )
205+
206+ expect ( encodeArc4 < uint64 [ ] > ( [ nativeNumber ] ) ) . toEqual ( new DynamicArray ( new UintN64 ( nativeNumber ) ) . bytes )
207+ expect ( encodeArc4 < boolean [ ] > ( [ nativeBool ] ) ) . toEqual ( new DynamicArray ( new Bool ( nativeBool ) ) . bytes )
208+ expect ( encodeArc4 < biguint [ ] > ( [ nativeBigInt ] ) ) . toEqual ( new DynamicArray ( new UintN < 512 > ( nativeBigInt ) ) . bytes )
209+ expect ( encodeArc4 < bytes [ ] > ( [ nativeBytes ] ) ) . toEqual ( new DynamicArray ( new DynamicBytes ( nativeBytes ) ) . bytes )
210+ expect ( encodeArc4 < string [ ] > ( [ nativeString ] ) ) . toEqual ( new DynamicArray ( new Str ( nativeString ) ) . bytes )
211+ expect ( encodeArc4 < Address [ ] > ( [ address ] ) ) . toEqual ( new DynamicArray ( address ) . bytes )
212+ } )
134213} )
135214
136215class StaticStruct extends Struct < {
0 commit comments