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
20 changes: 10 additions & 10 deletions docs/code/modules/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -575,7 +575,7 @@ the estimated rate.

#### Defined in

[src/transaction/transaction.ts:1078](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/transaction/transaction.ts#L1078)
[src/transaction/transaction.ts:1104](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/transaction/transaction.ts#L1104)

___

Expand Down Expand Up @@ -639,7 +639,7 @@ Allows for control of fees on a `Transaction` or `SuggestedParams` object

#### Defined in

[src/transaction/transaction.ts:1105](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/transaction/transaction.ts#L1105)
[src/transaction/transaction.ts:1131](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/transaction/transaction.ts#L1131)

___

Expand Down Expand Up @@ -967,7 +967,7 @@ Converts `bigint`'s for Uint's < 64 to `number` for easier use.

#### Defined in

[src/transaction/transaction.ts:944](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/transaction/transaction.ts#L944)
[src/transaction/transaction.ts:970](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/transaction/transaction.ts#L970)

___

Expand Down Expand Up @@ -1943,7 +1943,7 @@ Returns the array of transactions currently present in the given `AtomicTransact

#### Defined in

[src/transaction/transaction.ts:1154](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/transaction/transaction.ts#L1154)
[src/transaction/transaction.ts:1180](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/transaction/transaction.ts#L1180)

___

Expand Down Expand Up @@ -2330,7 +2330,7 @@ Returns suggested transaction parameters from algod unless some are already prov

#### Defined in

[src/transaction/transaction.ts:1132](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/transaction/transaction.ts#L1132)
[src/transaction/transaction.ts:1158](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/transaction/transaction.ts#L1158)

___

Expand Down Expand Up @@ -2762,7 +2762,7 @@ A new ATC with the resources populated into the transactions

#### Defined in

[src/transaction/transaction.ts:388](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/transaction/transaction.ts#L388)
[src/transaction/transaction.ts:414](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/transaction/transaction.ts#L414)

___

Expand Down Expand Up @@ -2791,7 +2791,7 @@ A new ATC with the changes applied

#### Defined in

[src/transaction/transaction.ts:407](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/transaction/transaction.ts#L407)
[src/transaction/transaction.ts:433](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/transaction/transaction.ts#L433)

___

Expand Down Expand Up @@ -2941,7 +2941,7 @@ An object with transaction IDs, transactions, group transaction ID (`groupTransa

#### Defined in

[src/transaction/transaction.ts:804](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/transaction/transaction.ts#L804)
[src/transaction/transaction.ts:830](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/transaction/transaction.ts#L830)

___

Expand Down Expand Up @@ -2970,7 +2970,7 @@ Signs and sends a group of [up to 16](https://dev.algorand.co/concepts/transacti

#### Defined in

[src/transaction/transaction.ts:977](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/transaction/transaction.ts#L977)
[src/transaction/transaction.ts:1003](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/transaction/transaction.ts#L1003)

___

Expand Down Expand Up @@ -3243,4 +3243,4 @@ Throws an error if the transaction is not confirmed or rejected in the next `tim

#### Defined in

[src/transaction/transaction.ts:1021](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/transaction/transaction.ts#L1021)
[src/transaction/transaction.ts:1047](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/transaction/transaction.ts#L1047)
84 changes: 83 additions & 1 deletion src/transaction/transaction.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { AlgoAmount } from '../types/amount'
import { AppClient } from '../types/app-client'
import { PaymentParams, TransactionComposer } from '../types/composer'
import { Arc2TransactionNote } from '../types/transaction'
import { getABIReturnValue, waitForConfirmation } from './transaction'
import { getABIReturnValue, populateAppCallResources, waitForConfirmation } from './transaction'

describe('transaction', () => {
const localnet = algorandFixture()
Expand Down Expand Up @@ -1138,6 +1138,88 @@ describe('Resource population: meta', () => {
expect(boxRef).toBeDefined()
expect(boxRef?.appIndex).toBe(0n)
})

test('order is deterministic', async () => {
const { algorand, context } = fixture

const testAccount = context.testAccount

const v9AppFactory = algorand.client.getAppFactory({
appSpec: JSON.stringify(v9ARC32),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want/need to test the ResourcePackerv8?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not needed because v8 is just txn-specific resources, thus we don't have any decisions to make regarding the order they are populated

defaultSender: testAccount,
})

const v9AppClient = (await v9AppFactory.send.create({ method: 'createApplication' })).appClient

await v9AppClient.fundAppAccount({ amount: (118_000).microAlgo() })

const accounts = []
for (let i = 0; i < 4; i++) {
accounts.push(algorand.account.random().addr)
}

const apps = []
for (let i = 0; i < 4; i++) {
const app = await v9AppFactory.send.create({ method: 'createApplication' })
apps.push(app.appClient.appId)
}

const assets = []
for (let i = 0; i < 4; i++) {
const res = await algorand.send.assetCreate({ sender: testAccount, total: 1n })
assets.push(res.assetId)
}

const appCall = await v9AppClient.params.call({
method: 'manyResources',
args: [accounts, assets, apps, [1, 2, 3, 4]],
})

const composer = algorand.newGroup()

composer.addAppCallMethodCall(appCall)

for (let i = 0; i < 10; i++) {
composer.addAppCallMethodCall(await v9AppClient.params.call({ method: 'dummy', note: `${i}` }))
}

const atc = (await composer.build()).atc
const getResources = async () => {
const populatedAtc = await populateAppCallResources(atc, algorand.client.algod)

const resources = []
for (const txnWithSigner of populatedAtc.buildGroup()) {
const txn = txnWithSigner.txn

for (const acct of txn.applicationCall?.accounts ?? []) {
resources.push(acct.toString())
}

for (const asset of txn.applicationCall?.foreignAssets ?? []) {
resources.push(asset.toString())
}

for (const app of txn.applicationCall?.foreignApps ?? []) {
resources.push(app.toString())
}

for (const box of txn.applicationCall?.boxes ?? []) {
resources.push(`${box.appIndex}-${box.name.toString()}`)
}
}

return resources
}

const allResources = []
for (let i = 0; i < 100; i++) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

100 iterations takes ~800ms on my machine. I think it's good enough to feel confident that it is indeed deterministic

allResources.push(await getResources())
}

for (let i = 1; i < allResources.length; i++) {
expect(allResources[i]).toEqual(allResources[0])
}
})
})

describe('abi return', () => {
Expand Down
28 changes: 27 additions & 1 deletion src/transaction/transaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -329,8 +329,34 @@ async function getGroupExecutionInfo(
throw Error(`Error resolving execution info via simulate in transaction ${groupResponse.failedAt}: ${groupResponse.failureMessage}`)
}

const sortedResources = groupResponse.unnamedResourcesAccessed

// NOTE: We explicitly want to avoid localeCompare as that can lead to different results in different environments
const compare = (a: string | bigint, b: string | bigint) => (a < b ? -1 : a > b ? 1 : 0)

if (sortedResources) {
sortedResources.accounts?.sort((a, b) => compare(a.toString(), b.toString()))
sortedResources.assets?.sort(compare)
sortedResources.apps?.sort(compare)
sortedResources.boxes?.sort((a, b) => {
const aStr = `${a.app}-${a.name}`
const bStr = `${b.app}-${b.name}`
return compare(aStr, bStr)
})
sortedResources.appLocals?.sort((a, b) => {
const aStr = `${a.app}-${a.account}`
const bStr = `${b.app}-${b.account}`
return compare(aStr, bStr)
})
sortedResources.assetHoldings?.sort((a, b) => {
const aStr = `${a.asset}-${a.account}`
const bStr = `${b.asset}-${b.account}`
return compare(aStr, bStr)
})
}

return {
groupUnnamedResourcesAccessed: sendParams.populateAppCallResources ? groupResponse.unnamedResourcesAccessed : undefined,
groupUnnamedResourcesAccessed: sendParams.populateAppCallResources ? sortedResources : undefined,
txns: groupResponse.txnResults.map((txn, i) => {
const originalTxn = atc['transactions'][i].txn as algosdk.Transaction

Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
}
},
"source": {
"approval": "I3ByYWdtYSB2ZXJzaW9uIDEwCmludGNibG9jayAxCgovLyBUaGlzIFRFQUwgd2FzIGdlbmVyYXRlZCBieSBURUFMU2NyaXB0IHYwLjEwNi4zCi8vIGh0dHBzOi8vZ2l0aHViLmNvbS9hbGdvcmFuZGZvdW5kYXRpb24vVEVBTFNjcmlwdAoKLy8gVGhpcyBjb250cmFjdCBpcyBjb21wbGlhbnQgd2l0aCBhbmQvb3IgaW1wbGVtZW50cyB0aGUgZm9sbG93aW5nIEFSQ3M6IFsgQVJDNCBdCgovLyBUaGUgZm9sbG93aW5nIHRlbiBsaW5lcyBvZiBURUFMIGhhbmRsZSBpbml0aWFsIHByb2dyYW0gZmxvdwovLyBUaGlzIHBhdHRlcm4gaXMgdXNlZCB0byBtYWtlIGl0IGVhc3kgZm9yIGFueW9uZSB0byBwYXJzZSB0aGUgc3RhcnQgb2YgdGhlIHByb2dyYW0gYW5kIGRldGVybWluZSBpZiBhIHNwZWNpZmljIGFjdGlvbiBpcyBhbGxvd2VkCi8vIEhlcmUsIGFjdGlvbiByZWZlcnMgdG8gdGhlIE9uQ29tcGxldGUgaW4gY29tYmluYXRpb24gd2l0aCB3aGV0aGVyIHRoZSBhcHAgaXMgYmVpbmcgY3JlYXRlZCBvciBjYWxsZWQKLy8gRXZlcnkgcG9zc2libGUgYWN0aW9uIGZvciB0aGlzIGNvbnRyYWN0IGlzIHJlcHJlc2VudGVkIGluIHRoZSBzd2l0Y2ggc3RhdGVtZW50Ci8vIElmIHRoZSBhY3Rpb24gaXMgbm90IGltcGxlbWVudGVkIGluIHRoZSBjb250cmFjdCwgaXRzIHJlc3BlY3RpdmUgYnJhbmNoIHdpbGwgYmUgIipOT1RfSU1QTEVNRU5URUQiIHdoaWNoIGp1c3QgY29udGFpbnMgImVyciIKdHhuIEFwcGxpY2F0aW9uSUQKIQpwdXNoaW50IDYKKgp0eG4gT25Db21wbGV0aW9uCisKc3dpdGNoICpjYWxsX05vT3AgKk5PVF9JTVBMRU1FTlRFRCAqTk9UX0lNUExFTUVOVEVEICpOT1RfSU1QTEVNRU5URUQgKk5PVF9JTVBMRU1FTlRFRCAqTk9UX0lNUExFTUVOVEVEICpjcmVhdGVfTm9PcCAqTk9UX0lNUExFTUVOVEVEICpOT1RfSU1QTEVNRU5URUQgKk5PVF9JTVBMRU1FTlRFRCAqTk9UX0lNUExFTUVOVEVEICpOT1RfSU1QTEVNRU5URUQKCipOT1RfSU1QTEVNRU5URUQ6CgkvLyBUaGUgcmVxdWVzdGVkIGFjdGlvbiBpcyBub3QgaW1wbGVtZW50ZWQgaW4gdGhpcyBjb250cmFjdC4gQXJlIHlvdSB1c2luZyB0aGUgY29ycmVjdCBPbkNvbXBsZXRlPyBEaWQgeW91IHNldCB5b3VyIGFwcCBJRD8KCWVycgoKLy8gY3JlYXRlRW1wdHlCb3goKXZvaWQKKmFiaV9yb3V0ZV9jcmVhdGVFbXB0eUJveDoKCS8vIGV4ZWN1dGUgY3JlYXRlRW1wdHlCb3goKXZvaWQKCWNhbGxzdWIgY3JlYXRlRW1wdHlCb3gKCWludGMgMCAvLyAxCglyZXR1cm4KCi8vIGNyZWF0ZUVtcHR5Qm94KCk6IHZvaWQKY3JlYXRlRW1wdHlCb3g6Cglwcm90byAwIDAKCgkvLyB0ZXN0cy9leGFtcGxlLWNvbnRyYWN0cy9yZXNvdXJjZS1wYWNrZXIvcmVzb3VyY2UtcGFja2VyLmFsZ28udHM6NjEKCS8vIHRoaXMuZW1wdHlCb3guY3JlYXRlKCkKCXB1c2hieXRlcyAweDY1NmQ3MDc0Nzk0MjZmNzggLy8gImVtcHR5Qm94IgoJcHVzaGludCAwCglib3hfY3JlYXRlCglwb3AKCXJldHN1YgoKKmFiaV9yb3V0ZV9jcmVhdGVBcHBsaWNhdGlvbjoKCWludGMgMCAvLyAxCglyZXR1cm4KCipjcmVhdGVfTm9PcDoKCXB1c2hieXRlcyAweGI4NDQ3YjM2IC8vIG1ldGhvZCAiY3JlYXRlQXBwbGljYXRpb24oKXZvaWQiCgl0eG5hIEFwcGxpY2F0aW9uQXJncyAwCgltYXRjaCAqYWJpX3JvdXRlX2NyZWF0ZUFwcGxpY2F0aW9uCgoJLy8gdGhpcyBjb250cmFjdCBkb2VzIG5vdCBpbXBsZW1lbnQgdGhlIGdpdmVuIEFCSSBtZXRob2QgZm9yIGNyZWF0ZSBOb09wCgllcnIKCipjYWxsX05vT3A6CglwdXNoYnl0ZXMgMHhhNjhiZDI5NyAvLyBtZXRob2QgImNyZWF0ZUVtcHR5Qm94KCl2b2lkIgoJdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMAoJbWF0Y2ggKmFiaV9yb3V0ZV9jcmVhdGVFbXB0eUJveAoKCS8vIHRoaXMgY29udHJhY3QgZG9lcyBub3QgaW1wbGVtZW50IHRoZSBnaXZlbiBBQkkgbWV0aG9kIGZvciBjYWxsIE5vT3AKCWVycg==",
"approval": "I3ByYWdtYSB2ZXJzaW9uIDEwCmludGNibG9jayAxCgovLyBUaGlzIFRFQUwgd2FzIGdlbmVyYXRlZCBieSBURUFMU2NyaXB0IHYwLjEwNi4zCi8vIGh0dHBzOi8vZ2l0aHViLmNvbS9hbGdvcmFuZGZvdW5kYXRpb24vVEVBTFNjcmlwdAoKLy8gVGhpcyBjb250cmFjdCBpcyBjb21wbGlhbnQgd2l0aCBhbmQvb3IgaW1wbGVtZW50cyB0aGUgZm9sbG93aW5nIEFSQ3M6IFsgQVJDNCBdCgovLyBUaGUgZm9sbG93aW5nIHRlbiBsaW5lcyBvZiBURUFMIGhhbmRsZSBpbml0aWFsIHByb2dyYW0gZmxvdwovLyBUaGlzIHBhdHRlcm4gaXMgdXNlZCB0byBtYWtlIGl0IGVhc3kgZm9yIGFueW9uZSB0byBwYXJzZSB0aGUgc3RhcnQgb2YgdGhlIHByb2dyYW0gYW5kIGRldGVybWluZSBpZiBhIHNwZWNpZmljIGFjdGlvbiBpcyBhbGxvd2VkCi8vIEhlcmUsIGFjdGlvbiByZWZlcnMgdG8gdGhlIE9uQ29tcGxldGUgaW4gY29tYmluYXRpb24gd2l0aCB3aGV0aGVyIHRoZSBhcHAgaXMgYmVpbmcgY3JlYXRlZCBvciBjYWxsZWQKLy8gRXZlcnkgcG9zc2libGUgYWN0aW9uIGZvciB0aGlzIGNvbnRyYWN0IGlzIHJlcHJlc2VudGVkIGluIHRoZSBzd2l0Y2ggc3RhdGVtZW50Ci8vIElmIHRoZSBhY3Rpb24gaXMgbm90IGltcGxlbWVudGVkIGluIHRoZSBjb250cmFjdCwgaXRzIHJlc3BlY3RpdmUgYnJhbmNoIHdpbGwgYmUgIipOT1RfSU1QTEVNRU5URUQiIHdoaWNoIGp1c3QgY29udGFpbnMgImVyciIKdHhuIEFwcGxpY2F0aW9uSUQKIQpwdXNoaW50IDYKKgp0eG4gT25Db21wbGV0aW9uCisKc3dpdGNoICpjYWxsX05vT3AgKk5PVF9JTVBMRU1FTlRFRCAqTk9UX0lNUExFTUVOVEVEICpOT1RfSU1QTEVNRU5URUQgKk5PVF9JTVBMRU1FTlRFRCAqTk9UX0lNUExFTUVOVEVEICpjcmVhdGVfTm9PcCAqTk9UX0lNUExFTUVOVEVEICpOT1RfSU1QTEVNRU5URUQgKk5PVF9JTVBMRU1FTlRFRCAqTk9UX0lNUExFTUVOVEVEICpOT1RfSU1QTEVNRU5URUQKCipOT1RfSU1QTEVNRU5URUQ6CgkvLyBUaGUgcmVxdWVzdGVkIGFjdGlvbiBpcyBub3QgaW1wbGVtZW50ZWQgaW4gdGhpcyBjb250cmFjdC4gQXJlIHlvdSB1c2luZyB0aGUgY29ycmVjdCBPbkNvbXBsZXRlPyBEaWQgeW91IHNldCB5b3VyIGFwcCBJRD8KCWVycgoKLy8gY3JlYXRlRW1wdHlCb3goKXZvaWQKKmFiaV9yb3V0ZV9jcmVhdGVFbXB0eUJveDoKCS8vIGV4ZWN1dGUgY3JlYXRlRW1wdHlCb3goKXZvaWQKCWNhbGxzdWIgY3JlYXRlRW1wdHlCb3gKCWludGMgMCAvLyAxCglyZXR1cm4KCi8vIGNyZWF0ZUVtcHR5Qm94KCk6IHZvaWQKY3JlYXRlRW1wdHlCb3g6Cglwcm90byAwIDAKCgkvLyByZXNvdXJjZS1wYWNrZXIuYWxnby50czo2MQoJLy8gdGhpcy5lbXB0eUJveC5jcmVhdGUoKQoJcHVzaGJ5dGVzIDB4NjU2ZDcwNzQ3OTQyNmY3OCAvLyAiZW1wdHlCb3giCglwdXNoaW50IDAKCWJveF9jcmVhdGUKCXBvcAoJcmV0c3ViCgoqYWJpX3JvdXRlX2NyZWF0ZUFwcGxpY2F0aW9uOgoJaW50YyAwIC8vIDEKCXJldHVybgoKKmNyZWF0ZV9Ob09wOgoJcHVzaGJ5dGVzIDB4Yjg0NDdiMzYgLy8gbWV0aG9kICJjcmVhdGVBcHBsaWNhdGlvbigpdm9pZCIKCXR4bmEgQXBwbGljYXRpb25BcmdzIDAKCW1hdGNoICphYmlfcm91dGVfY3JlYXRlQXBwbGljYXRpb24KCgkvLyB0aGlzIGNvbnRyYWN0IGRvZXMgbm90IGltcGxlbWVudCB0aGUgZ2l2ZW4gQUJJIG1ldGhvZCBmb3IgY3JlYXRlIE5vT3AKCWVycgoKKmNhbGxfTm9PcDoKCXB1c2hieXRlcyAweGE2OGJkMjk3IC8vIG1ldGhvZCAiY3JlYXRlRW1wdHlCb3goKXZvaWQiCgl0eG5hIEFwcGxpY2F0aW9uQXJncyAwCgltYXRjaCAqYWJpX3JvdXRlX2NyZWF0ZUVtcHR5Qm94CgoJLy8gdGhpcyBjb250cmFjdCBkb2VzIG5vdCBpbXBsZW1lbnQgdGhlIGdpdmVuIEFCSSBtZXRob2QgZm9yIGNhbGwgTm9PcAoJZXJy",
"clear": "I3ByYWdtYSB2ZXJzaW9uIDEw"
},
"contract": {
Expand Down
Loading