Skip to content

Commit ed4fd56

Browse files
authored
Merge pull request #17 from algorandfoundation/refactor-sdk-utils
refactor: remove dependency on algosdk, move algokit-utils to dev
2 parents 0480033 + cbbc86a commit ed4fd56

28 files changed

+1684
-771
lines changed

package-lock.json

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

package.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
"build-examples": "rollup --config examples/rollup.config.ts --configPlugin typescript"
2626
},
2727
"devDependencies": {
28+
"@algorandfoundation/algokit-utils": "^8.0.3",
2829
"@commitlint/cli": "^19.5.0",
2930
"@commitlint/config-conventional": "^19.5.0",
3031
"@eslint/eslintrc": "3.1.0",
@@ -62,10 +63,8 @@
6263
"tslib": "^2.6.2"
6364
},
6465
"dependencies": {
65-
"@algorandfoundation/algokit-utils": "^6.2.1",
6666
"@algorandfoundation/algorand-typescript": "^0.0.1-alpha.22",
6767
"@algorandfoundation/puya-ts": "^1.0.0-alpha.34",
68-
"algosdk": "^2.9.0",
6968
"elliptic": "^6.5.7",
7069
"js-sha256": "^0.11.0",
7170
"js-sha3": "^0.9.3",

src/abi-metadata.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { BaseContract, Contract } from '@algorandfoundation/algorand-typescript'
22
import { AbiMethodConfig, BareMethodConfig, CreateOptions, OnCompleteActionStr } from '@algorandfoundation/algorand-typescript/arc4'
3-
import { ABIMethod } from 'algosdk'
3+
import { sha512_256 as js_sha512_256 } from 'js-sha512'
44
import { TypeInfo } from './encoders'
55
import { getArc4TypeName as getArc4TypeNameForARC4Encoded } from './impl/encoded-types'
66
import { DeliberateAny } from './typescript-helpers'
@@ -73,12 +73,16 @@ export const getArc4Signature = (metadata: AbiMetadata): string => {
7373
if (metadata.methodSignature === undefined) {
7474
const argTypes = metadata.argTypes.map((t) => JSON.parse(t) as TypeInfo).map(getArc4TypeName)
7575
const returnType = getArc4TypeName(JSON.parse(metadata.returnType) as TypeInfo)
76-
const method = new ABIMethod({ name: metadata.methodName, args: argTypes.map((t) => ({ type: t })), returns: { type: returnType } })
77-
metadata.methodSignature = method.getSignature()
76+
metadata.methodSignature = `${metadata.methodName}(${argTypes.join(',')})${returnType}`
7877
}
7978
return metadata.methodSignature
8079
}
8180

81+
export const getArc4Selector = (metadata: AbiMetadata): Uint8Array => {
82+
const hash = js_sha512_256.array(getArc4Signature(metadata))
83+
return new Uint8Array(hash.slice(0, 4))
84+
}
85+
8286
const getArc4TypeName = (t: TypeInfo): string => {
8387
const map: Record<string, string | ((t: TypeInfo) => string)> = {
8488
void: 'void',

src/constants.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,3 +43,22 @@ export const ABI_RETURN_VALUE_LOG_PREFIX = Bytes.fromHex('151F7C75')
4343

4444
export const UINT64_OVERFLOW_UNDERFLOW_MESSAGE = 'Uint64 overflow or underflow'
4545
export const BIGUINT_OVERFLOW_UNDERFLOW_MESSAGE = 'BigUint overflow or underflow'
46+
47+
export const APP_ID_PREFIX = 'appID'
48+
export const HASH_BYTES_LENGTH = 32
49+
export const ALGORAND_ADDRESS_BYTE_LENGTH = 36
50+
export const ALGORAND_CHECKSUM_BYTE_LENGTH = 4
51+
export const ALGORAND_ADDRESS_LENGTH = 58
52+
53+
export const PROGRAM_TAG = 'Program'
54+
55+
export const TRANSACTION_GROUP_MAX_SIZE = 16
56+
57+
export enum OnApplicationComplete {
58+
NoOpOC = 0,
59+
OptInOC = 1,
60+
CloseOutOC = 2,
61+
ClearStateOC = 3,
62+
UpdateApplicationOC = 4,
63+
DeleteApplicationOC = 5,
64+
}

src/impl/application.ts

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
1-
import { Account, Application, Bytes, bytes, LocalState, uint64 } from '@algorandfoundation/algorand-typescript'
2-
import algosdk from 'algosdk'
1+
import { Account, Application, bytes, LocalState, uint64 } from '@algorandfoundation/algorand-typescript'
32
import { BytesMap } from '../collections/custom-key-map'
43
import { ALWAYS_APPROVE_TEAL_PROGRAM } from '../constants'
54
import { lazyContext } from '../context-helpers/internal-context'
65
import { Mutable } from '../typescript-helpers'
7-
import { asBigInt, asUint64 } from '../util'
6+
import { asUint64, getApplicationAddress } from '../util'
87
import { Uint64BackedCls } from './base'
98
import { GlobalStateCls } from './state'
109

@@ -76,7 +75,6 @@ export class ApplicationCls extends Uint64BackedCls implements Application {
7675
return this.data.application.creator
7776
}
7877
get address(): Account {
79-
const addr = algosdk.getApplicationAddress(asBigInt(this.id))
80-
return Account(Bytes.fromBase32(addr))
78+
return getApplicationAddress(this.id)
8179
}
8280
}

src/impl/crypto.ts

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
11
import { arc4, bytes, Bytes, Ecdsa, gtxn, internal, VrfVerify } from '@algorandfoundation/algorand-typescript'
2-
import algosdk from 'algosdk'
32
import { ec } from 'elliptic'
43
import { sha256 as js_sha256 } from 'js-sha256'
54
import { keccak256 as js_keccak256, sha3_256 as js_sha3_256 } from 'js-sha3'
65
import { sha512_256 as js_sha512_256 } from 'js-sha512'
76
import nacl from 'tweetnacl'
8-
import { LOGIC_DATA_PREFIX } from '../constants'
7+
import { LOGIC_DATA_PREFIX, PROGRAM_TAG } from '../constants'
98
import { lazyContext } from '../context-helpers/internal-context'
109
import { notImplementedError } from '../errors'
11-
import { asBytes, asBytesCls } from '../util'
10+
import { asBytes, asBytesCls, asUint8Array, conactUint8Arrays } from '../util'
1211

1312
export const sha256 = (a: internal.primitives.StubBytesCompat): bytes => {
1413
const bytesA = internal.primitives.BytesCls.fromCompat(a)
@@ -59,10 +58,10 @@ export const ed25519verify = (
5958
txn.onCompletion == arc4.OnCompleteAction[arc4.OnCompleteAction.ClearState] ? txn.clearStateProgram : txn.approvalProgram,
6059
)
6160

62-
const logicSig = new algosdk.LogicSig(programBytes.asUint8Array())
63-
const decodedAddress = algosdk.decodeAddress(logicSig.address())
61+
const logicSig = conactUint8Arrays(asUint8Array(PROGRAM_TAG), programBytes.asUint8Array())
62+
const logicSigAddress = js_sha512_256.array(logicSig)
6463

65-
const addressBytes = Bytes(decodedAddress.publicKey)
64+
const addressBytes = Bytes(logicSigAddress)
6665
const data = LOGIC_DATA_PREFIX.concat(addressBytes).concat(asBytes(a))
6766
return ed25519verifyBare(data, b, c)
6867
}

src/impl/encoded-types.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,14 @@ import {
1616
UintN,
1717
} from '@algorandfoundation/algorand-typescript/arc4'
1818
import { encodingUtil } from '@algorandfoundation/puya-ts'
19-
import { decodeAddress } from 'algosdk'
2019
import assert from 'assert'
21-
import { ABI_RETURN_VALUE_LOG_PREFIX, BITS_IN_BYTE, UINT64_SIZE } from '../constants'
20+
import {
21+
ABI_RETURN_VALUE_LOG_PREFIX,
22+
ALGORAND_ADDRESS_BYTE_LENGTH,
23+
ALGORAND_CHECKSUM_BYTE_LENGTH,
24+
BITS_IN_BYTE,
25+
UINT64_SIZE,
26+
} from '../constants'
2227
import { fromBytes, TypeInfo } from '../encoders'
2328
import { DeliberateAny } from '../typescript-helpers'
2429
import { asBigUint, asBigUintCls, asBytesCls, asUint64, asUint8Array, conactUint8Arrays, uint8ArrayToNumber } from '../util'
@@ -429,7 +434,7 @@ export class AddressImpl extends Address {
429434
if (value === undefined) {
430435
uint8ArrayValue = new Uint8Array(32)
431436
} else if (typeof value === 'string') {
432-
uint8ArrayValue = decodeAddress(value).publicKey
437+
uint8ArrayValue = encodingUtil.base32ToUint8Array(value).slice(0, ALGORAND_ADDRESS_BYTE_LENGTH - ALGORAND_CHECKSUM_BYTE_LENGTH)
433438
} else if (internal.primitives.isBytes(value)) {
434439
uint8ArrayValue = internal.primitives.getUint8Array(value)
435440
} else {

src/impl/global.ts

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { Account, Application, Bytes, bytes, internal, op, Uint64, uint64 } from '@algorandfoundation/algorand-typescript'
2-
import algosdk from 'algosdk'
32
import {
43
DEFAULT_ACCOUNT_MIN_BALANCE,
54
DEFAULT_ASSET_CREATE_MIN_BALANCE,
@@ -10,7 +9,7 @@ import {
109
ZERO_ADDRESS,
1110
} from '../constants'
1211
import { lazyContext } from '../context-helpers/internal-context'
13-
import { asBigInt, getObjectReference } from '../util'
12+
import { getApplicationAddress, getObjectReference } from '../util'
1413

1514
export class GlobalData {
1615
minTxnFee: uint64
@@ -128,8 +127,7 @@ export const Global: internal.opTypes.GlobalType = {
128127
* Address that the current application controls. Application mode only.
129128
*/
130129
get currentApplicationAddress(): Account {
131-
const appAddress = algosdk.getApplicationAddress(asBigInt(this.currentApplicationId.id))
132-
return Account(Bytes.fromBase32(appAddress))
130+
return this.currentApplicationId.address
133131
},
134132

135133
/**
@@ -163,8 +161,7 @@ export const Global: internal.opTypes.GlobalType = {
163161
* The application address of the application that called this application. ZeroAddress if this application is at the top-level. Application mode only.
164162
*/
165163
get callerApplicationAddress(): Account {
166-
const appAddress = algosdk.getApplicationAddress(asBigInt(this.callerApplicationId))
167-
return Account(Bytes.fromBase32(appAddress))
164+
return getApplicationAddress(this.callerApplicationId)
168165
},
169166

170167
/**

src/subcontexts/contract-context.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,10 @@ import {
1010
internal,
1111
LocalState,
1212
} from '@algorandfoundation/algorand-typescript'
13-
import { ABIMethod } from 'algosdk'
1413
import {
1514
AbiMetadata,
1615
copyAbiMetadatas,
17-
getArc4Signature,
16+
getArc4Selector,
1817
getContractAbiMetadata,
1918
getContractMethodAbiMetadata,
2019
isContractProxy,
@@ -144,7 +143,7 @@ export class ContractContext {
144143
...args: TParams
145144
): Transaction[] {
146145
const app = lazyContext.ledger.getApplicationForContract(contract)
147-
const methodSelector = abiMetadata ? ABIMethod.fromSignature(getArc4Signature(abiMetadata)).getSelector() : new Uint8Array()
146+
const methodSelector = abiMetadata ? getArc4Selector(abiMetadata) : new Uint8Array()
148147
const { transactions, ...appCallArgs } = extractArraysFromArgs(app, methodSelector, args)
149148
const appTxn = lazyContext.any.txn.applicationCall({
150149
appId: app,

src/subcontexts/transaction-context.ts

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { bytes, Contract, internal, TransactionType, uint64 } from '@algorandfoundation/algorand-typescript'
2-
import algosdk from 'algosdk'
32
import { AbiMetadata, getContractMethodAbiMetadata } from '../abi-metadata'
3+
import { TRANSACTION_GROUP_MAX_SIZE } from '../constants'
44
import { lazyContext } from '../context-helpers/internal-context'
55
import { DecodedLogs, decodeLogs, LogDecoding } from '../decode-logs'
66
import { testInvariant } from '../errors'
@@ -180,10 +180,8 @@ export class TransactionGroup {
180180

181181
constructor(transactions: Transaction[], activeTransactionIndex?: number) {
182182
this.latestTimestamp = Date.now()
183-
if (transactions.length > algosdk.AtomicTransactionComposer.MAX_GROUP_SIZE) {
184-
internal.errors.internalError(
185-
`Transaction group can have at most ${algosdk.AtomicTransactionComposer.MAX_GROUP_SIZE} transactions, as per AVM limits.`,
186-
)
183+
if (transactions.length > TRANSACTION_GROUP_MAX_SIZE) {
184+
internal.errors.internalError(`Transaction group can have at most ${TRANSACTION_GROUP_MAX_SIZE} transactions, as per AVM limits.`)
187185
}
188186
transactions.forEach((txn, index) => Object.assign(txn, { groupIndex: asUint64(index) }))
189187
this.activeTransactionIndex = activeTransactionIndex === undefined ? transactions.length - 1 : activeTransactionIndex
@@ -245,8 +243,8 @@ export class TransactionGroup {
245243
if (!this.constructingItxnGroup.length) {
246244
internal.errors.internalError('itxn submit without itxn begin')
247245
}
248-
if (this.constructingItxnGroup.length > algosdk.AtomicTransactionComposer.MAX_GROUP_SIZE) {
249-
internal.errors.internalError('Cannot submit more than 16 inner transactions at once')
246+
if (this.constructingItxnGroup.length > TRANSACTION_GROUP_MAX_SIZE) {
247+
internal.errors.internalError(`Cannot submit more than ${TRANSACTION_GROUP_MAX_SIZE} inner transactions at once`)
250248
}
251249
const itxns = this.constructingItxnGroup.map((t) => createInnerTxn(t))
252250
itxns.forEach((itxn, index) => Object.assign(itxn, { groupIndex: asUint64(index) }))

0 commit comments

Comments
 (0)