Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Boxes: Add support for Boxes #604

Merged
merged 24 commits into from
Nov 2, 2022
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
a122ae1
Boxes for application calls in static array (#573)
algochoi Jun 30, 2022
077c572
GetApplicationBoxByName API (#586)
algochoi Jul 7, 2022
293b4d2
Box Storage: Add GetApplicationBoxes API and cucumber steps (#608)
algochoi Jul 15, 2022
cd50f02
Merge branch 'develop' into feature/box-storage
algochoi Aug 8, 2022
578ddf0
Enhancement: Merge `develop` to `feature/box-storage` (#640)
ahangsu Sep 3, 2022
dccb952
Merge branch 'develop' into feature/box-storage
ahangsu Sep 6, 2022
af80784
Box support for Indexer endpoints (#619)
algochoi Sep 6, 2022
4ca50f0
Merge branch 'develop' into feature/box-storage
ahangsu Sep 7, 2022
6e3b958
boxes integration algod test
ahangsu Sep 7, 2022
b45e83c
Enhancement: Boxes Indexer Integration test (#641)
ahangsu Sep 15, 2022
15e591b
remove unnecessary @applications tag
ahangsu Sep 20, 2022
82fb7fd
revert package-lock.json to develop
ahangsu Sep 20, 2022
5e97b5c
Box storage changes (#656)
jasonpaulos Sep 21, 2022
4026bf5
Re-order box args to avoid breaking changes (#660)
jasonpaulos Sep 26, 2022
075d8d0
Box storage merge develop (#668)
jasonpaulos Oct 12, 2022
e3bc11d
Merge branch 'develop' into feature/box-storage
jasonpaulos Oct 12, 2022
a1b54b7
Merge commit 'f34be5e1727dd0ea14be90067d3eca156965cba3' into feature/…
jasonpaulos Oct 12, 2022
7301db5
Merge branch 'develop' into feature/box-storage
jasonpaulos Oct 12, 2022
b527f9d
Code generation improvements for boxes (#662)
jasonpaulos Oct 12, 2022
4144112
Merge branch 'develop' into update_again
michaeldiamant Oct 31, 2022
ebbf77f
Regenerate sources from upstream AVM branches
michaeldiamant Oct 31, 2022
da4d12c
Merge branch 'develop' into update_again
michaeldiamant Oct 31, 2022
4499a96
Merge pull request #679 from michaeldiamant/update_again
michaeldiamant Oct 31, 2022
1ad96cd
Revert SDK_TESTING_BRANCH to master
michaeldiamant Nov 2, 2022
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
2 changes: 1 addition & 1 deletion .test-env
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Configs for testing repo download:
SDK_TESTING_URL="https://github.com/algorand/algorand-sdk-testing"
SDK_TESTING_BRANCH="master"
SDK_TESTING_BRANCH="feature/box-storage"
ahangsu marked this conversation as resolved.
Show resolved Hide resolved
michaeldiamant marked this conversation as resolved.
Show resolved Hide resolved
SDK_TESTING_HARNESS="test-harness"

VERBOSE_HARNESS=0
Expand Down
662 changes: 416 additions & 246 deletions package-lock.json

Large diffs are not rendered by default.

42 changes: 42 additions & 0 deletions src/boxStorage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { EncodedBoxReference } from './types';
import { BoxReference } from './types/transactions/base';

function translateBoxReference(
reference: BoxReference,
foreignApps: number[],
appIndex: number
): EncodedBoxReference {
const referenceId = reference.appIndex;
const referenceName = reference.name;
const isOwnReference = referenceId === 0 || referenceId === appIndex;
let index = 0;

if (foreignApps != null) {
// Foreign apps start from index 1; index 0 is its own app ID.
index = foreignApps.indexOf(referenceId) + 1;
}
// Check if the app referenced is itself after checking the foreign apps array.
// If index is zero, then the app ID was not found in the foreign apps array
// or the foreign apps array was null.
if (index === 0 && !isOwnReference) {
// Error if the app is trying to reference a foreign app that was not in
// its own foreign apps array.
throw new Error(`Box ref with appId ${referenceId} not in foreign-apps`);
}
return { i: index, n: referenceName };
}

/**
* translateBoxReferences translates an array of BoxReferences with app IDs
* into an array of EncodedBoxReferences with foreign indices.
*/
export function translateBoxReferences(
references: BoxReference[],
foreignApps: number[],
appIndex: number
): EncodedBoxReference[] {
if (!Array.isArray(references)) return [];
jasonpaulos marked this conversation as resolved.
Show resolved Hide resolved
return references.map((bx) =>
translateBoxReference(bx, foreignApps, appIndex)
);
}
37 changes: 37 additions & 0 deletions src/client/v2/algod/algod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import Dryrun from './dryrun';
import Genesis from './genesis';
import GetAssetByID from './getAssetByID';
import GetApplicationByID from './getApplicationByID';
import GetApplicationBoxByName from './getApplicationBoxByName';
import GetApplicationBoxes from './getApplicationBoxes';
import HealthCheck from './healthCheck';
import PendingTransactionInformation from './pendingTransactionInformation';
import PendingTransactions from './pendingTransactions';
Expand Down Expand Up @@ -431,6 +433,41 @@ export default class AlgodClient extends ServiceClient {
return new GetApplicationByID(this.c, this.intDecoding, index);
}

/**
* Given an application ID and the box name (key), return the value stored in the box.
*
* #### Example
* ```typescript
* const index = 60553466;
* const boxName = Buffer.from("foo");
* const boxValue = await algodClient.getApplicationBoxByName(index).name(boxName).do();
* ```
*
* [Response data schema details](https://developer.algorand.org/docs/rest-apis/algod/v2/#get-v2applicationsapplication-idbox)
* @param index - The application ID to look up.
* @category GET
*/
getApplicationBoxByName(index: number) {
jasonpaulos marked this conversation as resolved.
Show resolved Hide resolved
return new GetApplicationBoxByName(this.c, this.intDecoding, index);
}

/**
* Given an application ID, return all the box names associated with the app.
*
* #### Example
* ```typescript
* const index = 60553466;
* const boxesResult = await algodClient.getApplicationBoxes(index).max(3).do();
* ```
*
* [Response data schema details](https://developer.algorand.org/docs/rest-apis/algod/v2/#get-v2applicationsapplication-idboxes)
* @param index - The application ID to look up.
* @category GET
*/
getApplicationBoxes(index: number) {
return new GetApplicationBoxes(this.c, this.intDecoding, index);
}

/**
* Returns the entire genesis file.
*
Expand Down
55 changes: 55 additions & 0 deletions src/client/v2/algod/getApplicationBoxByName.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import JSONRequest from '../jsonrequest';
import HTTPClient from '../../client';
import IntDecoding from '../../../types/intDecoding';
import { BoxReference } from '../../../types';

/**
* Given an application ID and the box name (key), return the value stored in the box.
*
* #### Example
* ```typescript
* const index = 1234;
* const boxName = Buffer.from("foo");
* const boxValue = await algodClient.getApplicationBoxByName(index).name(boxName).do();
* ```
*
* [Response data schema details](https://developer.algorand.org/docs/rest-apis/algod/v2/#get-v2applicationsapplication-idbox)
* @param index - The application ID to look up.
* @category GET
*/
export default class GetApplicationBoxByName extends JSONRequest<BoxReference> {
constructor(c: HTTPClient, intDecoding: IntDecoding, private index: number) {
super(c, intDecoding);
this.index = index;
}

/**
* @returns `/v2/applications/${index}/box`
*/
path() {
return `/v2/applications/${this.index}/box`;
}

/**
* Box name in bytes, and encodes it into a b64 string with goal encoded prefix.
*
* #### Example
* ```typescript
* const boxName = Buffer.from("foo");
* const boxValue = await algodClient
* .getApplicationBoxByName(1234)
* .name(boxName)
* .do();
* ```
*
* @param name - name of box in bytes.
* @category query
*/
name(name: Uint8Array) {
// Encode query in base64 format and append the encoding prefix.
let encodedName = Buffer.from(name).toString('base64');
encodedName = `b64:${encodedName}`;
this.query.name = encodeURI(encodedName);
return this;
}
}
52 changes: 52 additions & 0 deletions src/client/v2/algod/getApplicationBoxes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import JSONRequest from '../jsonrequest';
import HTTPClient from '../../client';
import IntDecoding from '../../../types/intDecoding';
import { BoxesResponse } from './models/types';

/**
* Given an application ID, return all the box names associated with the app.
*
* #### Example
* ```typescript
* const index = 1234;
* const boxesResult = await algodClient.getApplicationBoxes(index).max(3).do();
* ```
*
* [Response data schema details](https://developer.algorand.org/docs/rest-apis/algod/v2/#get-v2applicationsapplication-idboxes)
* @param index - The application ID to look up.
* @category GET
*/
export default class GetApplicationBoxes extends JSONRequest<BoxesResponse> {
constructor(c: HTTPClient, intDecoding: IntDecoding, private index: number) {
super(c, intDecoding);
this.index = index;
this.query.max = 0;
}

/**
* @returns `/v2/applications/${index}/boxes`
*/
path() {
return `/v2/applications/${this.index}/boxes`;
}

/**
* Limit results for pagination.
*
* #### Example
* ```typescript
* const maxResults = 20;
* const boxesResult = await algodClient
* .GetApplicationBoxes(1234)
* .limit(maxResults)
* .do();
* ```
*
* @param limit - maximum number of results to return.
* @category query
*/
max(max: number) {
this.query.max = max;
return this;
}
}
84 changes: 83 additions & 1 deletion src/client/v2/algod/models/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1029,6 +1029,89 @@ export class BlockResponse extends BaseModel {
}
}

/**
* Box name and its content.
*/
export class Box extends BaseModel {
/**
* (name) box name, base64 encoded
*/
public name: Uint8Array;

/**
* (value) box value, base64 encoded.
*/
public value: Uint8Array;

/**
* Creates a new `Box` object.
* @param name - (name) box name, base64 encoded
* @param value - (value) box value, base64 encoded.
*/
constructor(name: string | Uint8Array, value: string | Uint8Array) {
super();
this.name =
typeof name === 'string'
? new Uint8Array(Buffer.from(name, 'base64'))
: name;
this.value =
typeof value === 'string'
? new Uint8Array(Buffer.from(value, 'base64'))
: value;

this.attribute_map = {
name: 'name',
value: 'value',
};
}
}

/**
* Box descriptor describes a Box.
*/
export class BoxDescriptor extends BaseModel {
/**
* Base64 encoded box name
*/
public name: Uint8Array;

/**
* Creates a new `BoxDescriptor` object.
* @param name - Base64 encoded box name
*/
constructor(name: string | Uint8Array) {
super();
this.name =
typeof name === 'string'
? new Uint8Array(Buffer.from(name, 'base64'))
: name;

this.attribute_map = {
name: 'name',
};
}
}

/**
* Box names of an application
*/
export class BoxesResponse extends BaseModel {
public boxes: BoxDescriptor[];

/**
* Creates a new `BoxesResponse` object.
* @param boxes -
*/
constructor(boxes: BoxDescriptor[]) {
super();
this.boxes = boxes;

this.attribute_map = {
boxes: 'boxes',
};
}
}

export class BuildVersion extends BaseModel {
public branch: string;

Expand Down Expand Up @@ -2111,7 +2194,6 @@ export class StateProof extends BaseModel {
typeof stateproof === 'string'
? new Uint8Array(Buffer.from(stateproof, 'base64'))
: stateproof;

this.attribute_map = {
message: 'Message',
stateproof: 'StateProof',
Expand Down
34 changes: 34 additions & 0 deletions src/client/v2/indexer/indexer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,12 @@ import LookupAccountCreatedApplications from './lookupAccountCreatedApplications
import LookupAssetByID from './lookupAssetByID';
import LookupApplications from './lookupApplications';
import LookupApplicationLogs from './lookupApplicationLogs';
import LookupApplicationBoxByIDandName from './lookupApplicationBoxByIDandName';
import SearchAccounts from './searchAccounts';
import SearchForTransactions from './searchForTransactions';
import SearchForAssets from './searchForAssets';
import SearchForApplications from './searchForApplications';
import SearchForApplicationBoxes from './searchForApplicationBoxes';
import { BaseHTTPClient } from '../../baseHTTPClient';
import {
CustomTokenHeader,
Expand Down Expand Up @@ -372,4 +374,36 @@ export default class IndexerClient extends ServiceClient {
searchForApplications() {
return new SearchForApplications(this.c, this.intDecoding);
}

/**
* Returns information about indexed application boxes.
*
* #### Example
* ```typescript
* const boxesResult = await indexerClient.searchForApplicationBoxes().do();
jasonpaulos marked this conversation as resolved.
Show resolved Hide resolved
* ```
*
* [Response data schema details](https://developer.algorand.org/docs/rest-apis/indexer/#get-v2applicationsapplication-idboxes)
* @param appID - The ID of the application with boxes.
* @category GET
*/
searchForApplicationBoxes(appID: number) {
return new SearchForApplicationBoxes(this.c, this.intDecoding, appID);
}

/**
* Returns information about the application box given its name.
*
* #### Example
* ```typescript
* const boxValue = await indexerClient.lookupApplicationBoxByIDandName().do();
jasonpaulos marked this conversation as resolved.
Show resolved Hide resolved
* ```
*
* [Response data schema details](https://developer.algorand.org/docs/rest-apis/indexer/#get-v2applicationsapplication-idbox)
* @param appID - The ID of the application with boxes.
* @category GET
*/
lookupApplicationBoxByIDandName(appID: number) {
return new LookupApplicationBoxByIDandName(this.c, this.intDecoding, appID);
}
}
Loading