Skip to content

Commit

Permalink
[account] Add ability for custom typed resource calls (#109)
Browse files Browse the repository at this point in the history
  • Loading branch information
gregnazario authored Oct 25, 2023
1 parent 90c412e commit 7af3db1
Show file tree
Hide file tree
Showing 9 changed files with 87 additions and 27 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ All notable changes to the Aptos TypeScript SDK will be captured in this file. T
- Fix client config not being added to the request
- Support to config a custom client instance
- Changed all Regex based inputs requiring a `0x` to be optional. This is to allow for easier copy/pasting of addresses and keys.
- Change GetAccountResource to take in a generic output type that matches the struct

## 0.0.0 (2023-10-18)

Expand Down
8 changes: 6 additions & 2 deletions examples/typescript/multi_agent_transfer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,12 @@ const TRANSFER_AMOUNT = 10;
*
*/
const balance = async (aptos: Aptos, name: string, address: AccountAddress) => {
let resource = await aptos.getAccountResource({ accountAddress: address.toUint8Array(), resourceType: COIN_STORE });
let amount = Number((resource.data as { coin: { value: string } }).coin.value);
type Coin = { coin: { value: string } };
let resource = await aptos.getAccountResource<Coin>({
accountAddress: address.toUint8Array(),
resourceType: COIN_STORE,
});
let amount = Number(resource.coin.value);

console.log(`${name}'s balance is: ${amount}`);
return amount;
Expand Down
8 changes: 6 additions & 2 deletions examples/typescript/simple_transfer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,12 @@ const TRANSFER_AMOUNT = 100;
*
*/
const balance = async (aptos: Aptos, name: string, address: AccountAddress) => {
let resource = await aptos.getAccountResource({ accountAddress: address.toUint8Array(), resourceType: COIN_STORE });
let amount = Number((resource.data as { coin: { value: string } }).coin.value);
type Coin = { coin: { value: string } };
let resource = await aptos.getAccountResource<Coin>({
accountAddress: address.toUint8Array(),
resourceType: COIN_STORE,
});
let amount = Number(resource.coin.value);

console.log(`${name}'s balance is: ${amount}`);
return amount;
Expand Down
8 changes: 6 additions & 2 deletions examples/typescript/transfer_coin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,12 @@ const TRANSFER_AMOUNT = 1_000_000;
*
*/
const balance = async (aptos: Aptos, name: string, address: AccountAddress) => {
let resource = await aptos.getAccountResource({ accountAddress: address.toUint8Array(), resourceType: COIN_STORE });
let amount = Number((resource.data as { coin: { value: string } }).coin.value);
type Coin = { coin: { value: string } };
let resource = await aptos.getAccountResource<Coin>({
accountAddress: address.toUint8Array(),
resourceType: COIN_STORE,
});
let amount = Number(resource.coin.value);

console.log(`${name}'s balance is: ${amount}`);
return amount;
Expand Down
11 changes: 6 additions & 5 deletions src/api/account.ts
Original file line number Diff line number Diff line change
Expand Up @@ -155,8 +155,10 @@ export class Account {
}

/**
* Queries a specific account resource given account address and resource type
* Queries a specific account resource given account address and resource type. Note that the default is `any` in order
* to allow for ease of accessing properties of the object.
*
* @type The typed output of the resource
* @param args.accountAddress Aptos account address
* @param args.resourceType String representation of an on-chain Move struct type, i.e "0x1::aptos_coin::AptosCoin"
* @param args.options.ledgerVersion The ledger version to query, if not provided it will get the latest version
Expand All @@ -166,17 +168,16 @@ export class Account {
* @example An example of an account resource
* ```
* {
* type: "0x1::aptos_coin::AptosCoin",
* data: { value: 6 }
* }
* ```
*/
async getAccountResource(args: {
async getAccountResource<T extends {} = any>(args: {
accountAddress: HexInput;
resourceType: MoveResourceType;
options?: LedgerVersion;
}): Promise<MoveResource> {
return getResource({ aptosConfig: this.config, ...args });
}): Promise<T> {
return getResource<T>({ aptosConfig: this.config, ...args });
}

/**
Expand Down
13 changes: 8 additions & 5 deletions src/internal/account.ts
Original file line number Diff line number Diff line change
Expand Up @@ -155,20 +155,20 @@ export async function getResources(args: {
});
}

export async function getResource(args: {
export async function getResource<T extends {}>(args: {
aptosConfig: AptosConfig;
accountAddress: HexInput;
resourceType: MoveResourceType;
options?: LedgerVersion;
}): Promise<MoveResource> {
}): Promise<T> {
const { aptosConfig, accountAddress, resourceType, options } = args;
const { data } = await getAptosFullNode<{}, MoveResource>({
aptosConfig,
originMethod: "getResource",
path: `accounts/${AccountAddress.fromHexInput(accountAddress).toString()}/resource/${resourceType}`,
params: { ledger_version: options?.ledgerVersion },
});
return data;
return data.data as T;
}

export async function lookupOriginalAccountAddress(args: {
Expand All @@ -177,7 +177,10 @@ export async function lookupOriginalAccountAddress(args: {
options?: LedgerVersion;
}): Promise<AccountAddress> {
const { aptosConfig, authenticationKey, options } = args;
const resource = await getResource({
type OriginatingAddress = {
address_map: { handle: string };
};
const resource = await getResource<OriginatingAddress>({
aptosConfig,
accountAddress: "0x1",
resourceType: "0x1::account::OriginatingAddress",
Expand All @@ -186,7 +189,7 @@ export async function lookupOriginalAccountAddress(args: {

const {
address_map: { handle },
} = resource.data as any;
} = resource;

// If the address is not found in the address map, which means its not rotated
// then return the address as is
Expand Down
58 changes: 50 additions & 8 deletions tests/e2e/api/account.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,22 +68,64 @@ describe("account api", () => {
expect(data.length).toBeGreaterThan(0);
});

test("it fetches an account resource", async () => {
test("it fetches an account resource without a type", async () => {
const config = new AptosConfig({ network: Network.LOCAL });
const aptos = new Aptos(config);
const data = await aptos.getAccountResource({
accountAddress: "0x1",
resourceType: "0x1::account::Account",
});
expect(data).toHaveProperty("type");
expect(data.type).toBe("0x1::account::Account");
expect(data).toHaveProperty("sequence_number");
expect(data.sequence_number).toBe("0");
expect(data).toHaveProperty("authentication_key");
expect(data.authentication_key).toBe("0x0000000000000000000000000000000000000000000000000000000000000001");
});

test("it fetches an account resource typed", async () => {
const config = new AptosConfig({ network: Network.LOCAL });
const aptos = new Aptos(config);
type AccountRes = {
authentication_key: string;
coin_register_events: {
counter: string;
guid: {
id: {
addr: string;
creation_num: string;
};
};
};
guid_creation_num: string;
key_rotation_events: {
counter: string;
guid: {
id: {
addr: string;
creation_num: string;
};
};
};
sequence_number: string;
};

const resource = await aptos.getAccountResource<AccountRes>({
accountAddress: "0x1",
resourceType: "0x1::account::Account",
});
expect(resource).toHaveProperty("sequence_number");
expect(resource.sequence_number).toBe("0");
expect(resource).toHaveProperty("authentication_key");
expect(resource.authentication_key).toBe("0x0000000000000000000000000000000000000000000000000000000000000001");
});

test("it fetches account transactions", async () => {
const config = new AptosConfig({ network: Network.LOCAL });
const aptos = new Aptos(config);
const senderAccount = Account.generate();
await aptos.fundAccount({ accountAddress: senderAccount.accountAddress.toString(), amount: FUND_AMOUNT });
await aptos.fundAccount({
accountAddress: senderAccount.accountAddress.toString(),
amount: FUND_AMOUNT,
});
const bob = Account.generate();
const rawTxn = await aptos.generateTransaction({
sender: senderAccount.accountAddress.toString(),
Expand Down Expand Up @@ -220,15 +262,15 @@ describe("account api", () => {
expect(data.length).toBeGreaterThan(0);
});

test("it fetches an account resource", async () => {
test("it fetches an account resource with partial information", async () => {
const config = new AptosConfig({ network: Network.LOCAL });
const aptos = new Aptos(config);
const data = await aptos.getAccountResource({
const data = await aptos.getAccountResource<{ authentication_key: string }>({
accountAddress: "0x1",
resourceType: "0x1::account::Account",
});
expect(data).toHaveProperty("type");
expect(data.type).toBe("0x1::account::Account");
expect(data).toHaveProperty("authentication_key");
expect(data.authentication_key).toBe("0x0000000000000000000000000000000000000000000000000000000000000001");
});
});
});
5 changes: 3 additions & 2 deletions tests/e2e/api/faucet.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,12 @@ describe("Faucet", () => {
await aptos.fundAccount({ accountAddress: testAccount.accountAddress.toString(), amount: FUND_AMOUNT });

// Check the balance
const resource = await aptos.getAccountResource({
type Coin = { coin: { value: string } };
const resource = await aptos.getAccountResource<Coin>({
accountAddress: testAccount.accountAddress.toString(),
resourceType: "0x1::coin::CoinStore<0x1::aptos_coin::AptosCoin>",
});
const amount = Number((resource.data as { coin: { value: string } }).coin.value);
const amount = Number(resource.coin.value);
expect(amount).toBe(FUND_AMOUNT);
});
});
2 changes: 1 addition & 1 deletion tests/e2e/api/general.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ describe("general api", () => {
},
],
},
} = resource.data as any;
} = resource as any;

const supply = await aptos.getTableItem({
handle,
Expand Down

0 comments on commit 7af3db1

Please sign in to comment.