Skip to content

Commit

Permalink
fix: Updating asset-transfer-transaction.amount and .closeAmount to a…
Browse files Browse the repository at this point in the history
…llow bigint values since they can be 64-bit numbers

BREAKING CHANGE: Indexer's from algokit.getAlgoIndexerClient(...) now have IntDecoding.MIXED rather than IntDecoding.DEFAULT
so that numbers > 53-bit will be accurately represented, you can override this with a new parameter to that function.

Also, a number of fields in types/indexer that can have 64-bit values have been changed from `number` to `number | bigint`.
  • Loading branch information
robdmoore committed Mar 26, 2024
1 parent 57abb96 commit 0ec9979
Show file tree
Hide file tree
Showing 8 changed files with 121 additions and 40 deletions.
2 changes: 1 addition & 1 deletion docs/capabilities/client.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ There are a number of ways to produce one of these configuration objects:
Once you have the configuration for a client, to get the client you can use the following functions:

- [`algokit.getAlgoClient(config)`](../code/modules/index.md#getalgoclient) - Returns an Algod client for the given configuration; the client automatically retries on transient HTTP errors; if one isn't provided it retrieves it from the environment
- [`algokit.getAlgoIndexerClient(config)`](../code/modules/index.md#getalgoindexerclient) - Returns an Indexer client for given configuration; if one isn't provided it retrieves it from the environment
- [`algokit.getAlgoIndexerClient(config, overrideIntDecoding)`](../code/modules/index.md#getalgoindexerclient) - Returns an Indexer client for given configuration; if one isn't provided it retrieves it from the environment
- [`algokit.getAlgoKmdClient(config)`](../code/modules/index.md#getalgokmdclient) - Returns a Kmd client for the given configuration; if one isn't provided it retrieves it from the environment

## Automatic retry
Expand Down
2 changes: 1 addition & 1 deletion docs/code/interfaces/types_indexer.AssetHolding.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ Describes an asset held by an account. https://developer.algorand.org/docs/rest-

### amount

**amount**: `number`
**amount**: `number` \| `bigint`

(a) number of units held.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ Fields for an asset transfer transaction. https://developer.algorand.org/docs/re

### amount

**amount**: `number`
**amount**: `number` \| `bigint`

[aamt] Amount of asset to transfer. A zero amount transferred to self allocates that asset in the account's Assets map.

Expand All @@ -45,7 +45,7 @@ ___

### close-amount

`Optional` **close-amount**: `number`
`Optional` **close-amount**: `number` \| `bigint`

Number of assets transfered to the close-to account as part of the transaction.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ are needed in order to verify the next state proofs (VotersCommitment and LnProv
| `block-headers-commitment` | `string` | [b] BlockHeadersCommitment contains a commitment on all light block headers within a state proof interval. |
| `first-attested-round` | `number` | [f] First round the message attests to |
| `latest-attested-round` | `number` | [l] Last round the message attests to |
| `ln-proven-weight` | `number` | [P] An integer value representing the natural log of the proven weight with 16 bits of precision. This value would be used to verify the next state proof. |
| `ln-proven-weight` | `number` \| `bigint` | [P] An integer value representing the natural log of the proven weight with 16 bits of precision. This value would be used to verify the next state proof. |
| `voters-commitment` | `string` | [v] The vector commitment root of the top N accounts to sign the next StateProof. Pattern : "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==\\|[A-Za-z0-9+/]{3}=)?$" |

#### Defined in
Expand All @@ -63,11 +63,11 @@ ___
| :------ | :------ | :------ |
| `part-proofs` | [`MerkleArrayProof`](types_indexer.MerkleArrayProof.md) | [P] Part proofs that make up the overall proof |
| `positions-to-reveal` | `number`[] | [pr] The positions that are revealed |
| `reveals` | \{ `participant`: \{ `verifier`: \{ `commitment`: `string` ; `key-lifetime`: `number` } ; `weight`: `number` } ; `position`: `number` ; `sig-slot`: \{ `lower-sig-weight`: `number` ; `signature`: \{ `falcon-signature`: `string` ; `merkle-array-index`: `number` ; `proof`: [`MerkleArrayProof`](types_indexer.MerkleArrayProof.md) ; `verifying-key`: `string` } } }[] | [r] Reveals is a sparse map from the position being revealed to the corresponding elements from the sigs and participants arrays. |
| `reveals` | \{ `participant`: \{ `verifier`: \{ `commitment`: `string` ; `key-lifetime`: `number` } ; `weight`: `number` \| `bigint` } ; `position`: `number` ; `sig-slot`: \{ `lower-sig-weight`: `number` \| `bigint` ; `signature`: \{ `falcon-signature`: `string` ; `merkle-array-index`: `number` ; `proof`: [`MerkleArrayProof`](types_indexer.MerkleArrayProof.md) ; `verifying-key`: `string` } } }[] | [r] Reveals is a sparse map from the position being revealed to the corresponding elements from the sigs and participants arrays. |
| `salt-version` | `number` | [v] Merkle signature salt version |
| `sig-commit` | `string` | [c] Digest of the signature commit |
| `sig-proofs` | [`MerkleArrayProof`](types_indexer.MerkleArrayProof.md) | [S] Proofs for the signature |
| `signed-weight` | `number` | [w] The combined weight of the signatures |
| `signed-weight` | `number` \| `bigint` | [w] The combined weight of the signatures |

#### Defined in

Expand Down
52 changes: 29 additions & 23 deletions docs/code/modules/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ algokit.bulkOptIn({ account: account, assetIds: [12345, 67890] }, algod)

#### Defined in

[src/asset.ts:237](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/asset.ts#L237)
[src/asset.ts:241](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/asset.ts#L241)

___

Expand Down Expand Up @@ -238,7 +238,7 @@ algokit.bulkOptOut({ account: account, assetIds: [12345, 67890] }, algod)

#### Defined in

[src/asset.ts:304](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/asset.ts#L304)
[src/asset.ts:308](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/asset.ts#L308)

___

Expand Down Expand Up @@ -269,7 +269,7 @@ await algokit.assetOptIn({ account, assetId }, algod)

#### Defined in

[src/asset.ts:148](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/asset.ts#L148)
[src/asset.ts:152](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/asset.ts#L152)

___

Expand Down Expand Up @@ -300,7 +300,7 @@ await algokit.assetOptOut({ account, assetId, assetCreatorAddress }, algod)

#### Defined in

[src/asset.ts:186](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/asset.ts#L186)
[src/asset.ts:190](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/asset.ts#L190)

___

Expand Down Expand Up @@ -437,7 +437,7 @@ ___

### createAsset

**createAsset**(`create`, `algod`): `Promise`\<[`SendTransactionResult`](../interfaces/types_transaction.SendTransactionResult.md)\>
**createAsset**(`create`, `algod`): `Promise`\<[`SendTransactionResult`](../interfaces/types_transaction.SendTransactionResult.md) & \{ `confirmation?`: \{ `assetIndex`: `number` \| `bigint` } }\>

Create an Algorand Standard Asset (ASA).

Expand All @@ -450,7 +450,7 @@ Create an Algorand Standard Asset (ASA).

#### Returns

`Promise`\<[`SendTransactionResult`](../interfaces/types_transaction.SendTransactionResult.md)\>
`Promise`\<[`SendTransactionResult`](../interfaces/types_transaction.SendTransactionResult.md) & \{ `confirmation?`: \{ `assetIndex`: `number` \| `bigint` } }\>

The transaction object and optionally the confirmation if it was sent to the chain (`skipSending` is `false` or unset)

Expand Down Expand Up @@ -655,7 +655,7 @@ ___

#### Defined in

[src/indexer-lookup.ts:133](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/indexer-lookup.ts#L133)
[src/indexer-lookup.ts:109](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/indexer-lookup.ts#L109)

___

Expand Down Expand Up @@ -920,13 +920,13 @@ Returns an algod SDK client that automatically retries on idempotent calls

#### Defined in

[src/network-client.ts:129](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/network-client.ts#L129)
[src/network-client.ts:130](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/network-client.ts#L130)

___

### getAlgoIndexerClient

**getAlgoIndexerClient**(`config?`): `Indexer`
**getAlgoIndexerClient**(`config?`, `overrideIntDecoding?`): `Indexer`

Returns an indexer SDK client that automatically retries on idempotent calls

Expand All @@ -935,6 +935,7 @@ Returns an indexer SDK client that automatically retries on idempotent calls
| Name | Type | Description |
| :------ | :------ | :------ |
| `config?` | [`AlgoClientConfig`](../interfaces/types_network_client.AlgoClientConfig.md) | The config if you want to override the default (getting config from process.env) |
| `overrideIntDecoding?` | `IntDecoding` | Override the default int decoding for responses, uses MIXED by default to avoid lost precision for big integers |

#### Returns

Expand All @@ -944,7 +945,6 @@ Returns an indexer SDK client that automatically retries on idempotent calls

```typescript
// Uses process.env.INDEXER_SERVER, process.env.INDEXER_PORT and process.env.INDEXER_TOKEN
// Automatically detects if you are using PureStake to switch in the right header name for INDEXER_TOKEN
const indexer = getAlgoIndexerClient()
await indexer.makeHealthCheck().do()
```
Expand All @@ -970,9 +970,15 @@ Returns an indexer SDK client that automatically retries on idempotent calls
await indexer.makeHealthCheck().do()
```

**`Example`**

```typescript
const indexer = getAlgoIndexerClient(config, IntDecoding.BIGINT)
```

#### Defined in

[src/network-client.ts:162](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/network-client.ts#L162)
[src/network-client.ts:167](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/network-client.ts#L167)

___

Expand Down Expand Up @@ -1009,7 +1015,7 @@ KMD client allows you to export private keys, which is useful to get the default

#### Defined in

[src/network-client.ts:185](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/network-client.ts#L185)
[src/network-client.ts:193](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/network-client.ts#L193)

___

Expand All @@ -1032,7 +1038,7 @@ Returns the Algorand configuration to point to the AlgoNode service

#### Defined in

[src/network-client.ts:75](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/network-client.ts#L75)
[src/network-client.ts:76](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/network-client.ts#L76)

___

Expand All @@ -1048,7 +1054,7 @@ Retrieve the algod configuration from environment variables (expects to be calle

#### Defined in

[src/network-client.ts:37](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/network-client.ts#L37)
[src/network-client.ts:38](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/network-client.ts#L38)

___

Expand Down Expand Up @@ -1549,7 +1555,7 @@ Retrieve configurations from environment variables when defined or get defaults

#### Defined in

[src/network-client.ts:10](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/network-client.ts#L10)
[src/network-client.ts:11](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/network-client.ts#L11)

___

Expand Down Expand Up @@ -1598,7 +1604,7 @@ Returns the Algorand configuration to point to the default LocalNet

#### Defined in

[src/network-client.ts:86](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/network-client.ts#L86)
[src/network-client.ts:87](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/network-client.ts#L87)

___

Expand Down Expand Up @@ -1640,7 +1646,7 @@ Retrieve the indexer configuration from environment variables (expects to be cal

#### Defined in

[src/network-client.ts:54](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/network-client.ts#L54)
[src/network-client.ts:55](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/network-client.ts#L55)

___

Expand Down Expand Up @@ -1910,7 +1916,7 @@ ___

#### Defined in

[src/network-client.ts:197](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/network-client.ts#L197)
[src/network-client.ts:205](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/network-client.ts#L205)

___

Expand Down Expand Up @@ -1957,7 +1963,7 @@ ___

#### Defined in

[src/network-client.ts:192](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/network-client.ts#L192)
[src/network-client.ts:200](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/network-client.ts#L200)

___

Expand All @@ -1982,7 +1988,7 @@ The result of the look-up

#### Defined in

[src/indexer-lookup.ts:54](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/indexer-lookup.ts#L54)
[src/indexer-lookup.ts:30](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/indexer-lookup.ts#L30)

___

Expand All @@ -2009,7 +2015,7 @@ The list of application results

#### Defined in

[src/indexer-lookup.ts:66](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/indexer-lookup.ts#L66)
[src/indexer-lookup.ts:42](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/indexer-lookup.ts#L42)

___

Expand All @@ -2034,7 +2040,7 @@ The result of the look-up

#### Defined in

[src/indexer-lookup.ts:42](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/indexer-lookup.ts#L42)
[src/indexer-lookup.ts:20](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/indexer-lookup.ts#L20)

___

Expand Down Expand Up @@ -2443,7 +2449,7 @@ The search results

#### Defined in

[src/indexer-lookup.ts:99](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/indexer-lookup.ts#L99)
[src/indexer-lookup.ts:75](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/indexer-lookup.ts#L75)

___

Expand Down
67 changes: 67 additions & 0 deletions src/indexer-lookup.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,4 +85,71 @@ describe('indexer-lookup', () => {

expect(apps.map((a) => a.id).sort()).toEqual([app1.appId, app2.appId].sort())
})

test('Asset transfer and creation transactions are found by search or by ID with amounts gt 53-bit', async () => {
const { algod, indexer, testAccount, generateAccount, waitForIndexer } = localnet.context
const secondAccount = await generateAccount({
initialFunds: algokit.algos(1),
suppressLog: true,
})
const asset = await algokit.createAsset(
{
creator: testAccount,
total: 135_640_597_783_270_615n,
decimals: 0,
},
algod,
)
await algokit.assetOptIn(
{
account: secondAccount,
assetId: Number(asset.confirmation!.assetIndex),
},
algod,
)
const transfer = await algokit.transferAsset(
{
amount: 134_640_597_783_270_615n,
from: testAccount,
to: secondAccount,
assetId: Number(asset.confirmation!.assetIndex),
},
algod,
)
const closeOut = await algokit.sendTransaction(
{
transaction: algosdk.makeAssetTransferTxnWithSuggestedParamsFromObject({
assetIndex: Number(asset.confirmation!.assetIndex),
from: algokit.getSenderAddress(secondAccount),
to: algokit.getSenderAddress(testAccount),
closeRemainderTo: algokit.getSenderAddress(testAccount),
amount: 257,
suggestedParams: await algokit.getTransactionParams(undefined, algod),
}),
from: secondAccount,
},
algod,
)
await waitForIndexer()

const searchTransactions = (await algokit.searchTransactions(indexer, (s) => s.assetID(Number(asset.confirmation!.assetIndex))))
.transactions

const acfgTxn = await algokit.lookupTransactionById(asset.transaction.txID(), indexer)
const acfgTxnFromSearch = searchTransactions.find((t) => t.id === asset.transaction.txID())!
expect(acfgTxn.transaction['asset-config-transaction']!.params!.total).toBe(135_640_597_783_270_615n)
expect(acfgTxnFromSearch['asset-config-transaction']!.params!.total).toBe(135_640_597_783_270_615n)

const axferTxn = await algokit.lookupTransactionById(transfer.transaction.txID(), indexer)
const axferTxnFromSearch = searchTransactions.find((t) => t.id === transfer.transaction.txID())!
expect(axferTxn.transaction['asset-transfer-transaction']!.amount).toBe(134_640_597_783_270_615n)
expect(axferTxnFromSearch['asset-transfer-transaction']!.amount).toBe(134_640_597_783_270_615n)

const closeOutTxn = await algokit.lookupTransactionById(closeOut.transaction.txID(), indexer)
const closeOutTxnFromSearch = searchTransactions.find((t) => t.id === closeOut.transaction.txID())!
expect(closeOutTxn.transaction['asset-transfer-transaction']!.amount).toBe(257)
expect(closeOutTxnFromSearch['asset-transfer-transaction']!.amount).toBe(257)
expect(closeOutTxn.transaction['asset-transfer-transaction']!['close-amount']).toBe(134_640_597_783_270_615n - 257n)
expect(closeOutTxnFromSearch['asset-transfer-transaction']!['close-amount']).toBe(134_640_597_783_270_615n - 257n)
})
})
14 changes: 11 additions & 3 deletions src/network-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { AlgoClientConfig, AlgoConfig } from './types/network-client'
import Algodv2 = algosdk.Algodv2
import Indexer = algosdk.Indexer
import Kmd = algosdk.Kmd
import IntDecoding = algosdk.IntDecoding

/** Retrieve configurations from environment variables when defined or get defaults (expects to be called from a Node.js environment not algod-side) */
export function getConfigFromEnvOrDefaults(): AlgoConfig {
Expand Down Expand Up @@ -135,11 +136,11 @@ export function getAlgoClient(config?: AlgoClientConfig): Algodv2 {
/** Returns an indexer SDK client that automatically retries on idempotent calls
*
* @param config The config if you want to override the default (getting config from process.env)
* @param overrideIntDecoding Override the default int decoding for responses, uses MIXED by default to avoid lost precision for big integers
* @example Default (load from environment variables)
*
* ```typescript
* // Uses process.env.INDEXER_SERVER, process.env.INDEXER_PORT and process.env.INDEXER_TOKEN
* // Automatically detects if you are using PureStake to switch in the right header name for INDEXER_TOKEN
* const indexer = getAlgoIndexerClient()
* await indexer.makeHealthCheck().do()
* ```
Expand All @@ -158,11 +159,18 @@ export function getAlgoClient(config?: AlgoClientConfig): Algodv2 {
* const indexer = getAlgoIndexerClient({server: 'http://localhost', port: '8980', token: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'})
* await indexer.makeHealthCheck().do()
* ```
* @example Override int decoding for responses
* ```typescript
* const indexer = getAlgoIndexerClient(config, IntDecoding.BIGINT)
* ```
*/
export function getAlgoIndexerClient(config?: AlgoClientConfig): Indexer {
export function getAlgoIndexerClient(config?: AlgoClientConfig, overrideIntDecoding?: IntDecoding): Indexer {
const { token, server, port } = config ?? getIndexerConfigFromEnvironment()
const httpClientWithRetry = new AlgoHttpClientWithRetry(getAlgoTokenHeader(server, token, 'X-Indexer-API-Token'), server, port)
return new Indexer(httpClientWithRetry)
const indexer = new Indexer(httpClientWithRetry)
// Use mixed int decoding by default so bigints don't have lost precision
indexer.setIntEncoding(overrideIntDecoding ?? IntDecoding.MIXED)
return indexer
}

/**
Expand Down
Loading

0 comments on commit 0ec9979

Please sign in to comment.