Skip to content

Commit

Permalink
[view] Add ability to get BCS output from view functions (#624)
Browse files Browse the repository at this point in the history
NOTE: this is temporary, needs to be fixed to have a completely separate
path in the SDK instead of the hack that is here.
  • Loading branch information
gregnazario authored Feb 11, 2025
1 parent cb4d657 commit 4503a0a
Show file tree
Hide file tree
Showing 16 changed files with 586 additions and 29 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ All notable changes to the Aptos TypeScript SDK will be captured in this file. T
# Unreleased

- Add `MultiEd25519Account` to support the legacy MultiEd25519 authentication scheme.
- Add `experimental` section to SDK
- Add experimental BCS support for view function outputs
- Upgrade to aptos-client 1.0.0 / remove override for cross-spawn

# 1.34.0 (2025-02-06)

Expand Down
3 changes: 2 additions & 1 deletion examples/typescript/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@
"local_node": "ts-node local_node.ts",
"public_key_authenticator_account_abstraction": "ts-node public_key_authenticator_account_abstraction.ts",
"hello_world_authenticator_account_abstraction": "ts-node hello_world_authenticator_account_abstraction.ts",
"test": "run-s simple_transfer multi_agent_transfer simple_sponsored_transaction transfer_coin custom_client publish_package_from_filepath external_signing sign_struct publish_package_from_filepath external_signing your_coin your_fungible_asset"
"view_bcs": "ts-node view_bcs.ts",
"test": "run-s simple_transfer multi_agent_transfer simple_sponsored_transaction transfer_coin custom_client publish_package_from_filepath external_signing sign_struct publish_package_from_filepath external_signing your_coin your_fungible_asset view_bcs"
},
"keywords": [],
"author": "",
Expand Down
105 changes: 105 additions & 0 deletions examples/typescript/view_bcs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
/* eslint-disable no-console */

/**
* This example shows how to use the Aptos client to create accounts, fund them, and transfer between them.
* Similar to ./simple_transfer.ts, but uses transferCoinTransaction to generate the transaction.
*/

import {
Account,
AccountAddress,
Aptos,
AptosConfig,
Deserializer,
Network,
NetworkToNetworkName,
U64,
} from "@aptos-labs/ts-sdk";

const ALICE_INITIAL_BALANCE = 100_000_000;
const BOB_INITIAL_BALANCE = 0;
const TRANSFER_AMOUNT = 1_000_000;

// Set up the client
const APTOS_NETWORK: Network = NetworkToNetworkName[process.env.APTOS_NETWORK ?? Network.DEVNET];
const config = new AptosConfig({ network: APTOS_NETWORK });
const aptos = new Aptos(config);

/**
* Prints the balance of an account
* @param name
* @param accountAddress
* @returns {Promise<number>}
*
*/
const balance = async (name: string, accountAddress: AccountAddress): Promise<number> => {
const output = await aptos.experimental.viewBinary({
payload: {
function: "0x1::coin::balance",
typeArguments: ["0x1::aptos_coin::AptosCoin"],
functionArguments: [accountAddress],
},
});
const deser = new Deserializer(output);
const [wrappedAmount] = deser.deserializeVector(U64);
const amount = Number(wrappedAmount.value);

console.log(`${name}'s balance is: ${amount}`);
return amount;
};

const example = async () => {
console.log(
"This example will create two accounts (Alice and Bob), fund Alice, and transfer between them using transferCoinTransaction.",
);

// Create two accounts
const alice = Account.generate();
const bob = Account.generate();

console.log("=== Addresses ===\n");
console.log(`Alice's address is: ${alice.accountAddress}`);
console.log(`Bob's address is: ${bob.accountAddress}`);

// Fund the accounts
console.log("\n=== Funding accounts ===\n");

// Fund alice account
await aptos.fundAccount({
accountAddress: alice.accountAddress,
amount: ALICE_INITIAL_BALANCE,
});

// Show the balances
console.log("\n=== Initial Balances ===\n");
const aliceBalance = await balance("Alice", alice.accountAddress);
const bobBalance = await balance("Bob", bob.accountAddress);

if (aliceBalance !== ALICE_INITIAL_BALANCE) throw new Error("Alice's balance is incorrect");
if (bobBalance !== BOB_INITIAL_BALANCE) throw new Error("Bob's balance is incorrect");

// Transfer between users
console.log(`\n=== Transfer ${TRANSFER_AMOUNT} from Alice to Bob ===\n`);
const transaction = await aptos.transferCoinTransaction({
sender: alice.accountAddress,
recipient: bob.accountAddress,
amount: TRANSFER_AMOUNT,
});
const pendingTxn = await aptos.signAndSubmitTransaction({ signer: alice, transaction });
const response = await aptos.waitForTransaction({ transactionHash: pendingTxn.hash });
console.log(`Committed transaction: ${response.hash}`);

console.log("\n=== Balances after transfer ===\n");
const newAliceBalance = await balance("Alice", alice.accountAddress);
const newBobBalance = await balance("Bob", bob.accountAddress);

// Bob should have the transfer amount
if (newBobBalance !== TRANSFER_AMOUNT + BOB_INITIAL_BALANCE)
throw new Error("Bob's balance after transfer is incorrect");

// Alice should have the remainder minus gas
if (newAliceBalance >= ALICE_INITIAL_BALANCE - TRANSFER_AMOUNT)
throw new Error("Alice's balance after transfer is incorrect");
};

example();
7 changes: 1 addition & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
},
"dependencies": {
"@aptos-labs/aptos-cli": "^1.0.2",
"@aptos-labs/aptos-client": "^0.1.1",
"@aptos-labs/aptos-client": "^1.0.0",
"@noble/curves": "^1.4.0",
"@noble/hashes": "^1.4.0",
"@scure/bip32": "^1.4.0",
Expand Down Expand Up @@ -97,10 +97,5 @@
"typedoc-plugin-missing-exports": "^3.0.0",
"typescript": "^5.6.2"
},
"pnpm": {
"overrides": {
"cross-spawn": ">=7.0.5"
}
},
"version": "1.34.0"
}
22 changes: 10 additions & 12 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions src/api/aptos.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { Table } from "./table";
import { Keyless } from "./keyless";
import { AptosObject } from "./object";
import { AccountAbstraction } from "./account/abstraction";
import { Experimental } from "./experimental";

/**
* The main entry point for interacting with the Aptos APIs,
Expand Down Expand Up @@ -55,6 +56,8 @@ export class Aptos {

readonly event: Event;

readonly experimental: Experimental;

readonly faucet: Faucet;

readonly fungibleAsset: FungibleAsset;
Expand Down Expand Up @@ -100,6 +103,7 @@ export class Aptos {
this.coin = new Coin(this.config);
this.digitalAsset = new DigitalAsset(this.config);
this.event = new Event(this.config);
this.experimental = new Experimental(this.config);
this.faucet = new Faucet(this.config);
this.fungibleAsset = new FungibleAsset(this.config);
this.general = new General(this.config);
Expand All @@ -119,6 +123,7 @@ export interface Aptos
Coin,
DigitalAsset,
Event,
Experimental,
Faucet,
FungibleAsset,
General,
Expand Down Expand Up @@ -156,6 +161,7 @@ applyMixin(Aptos, ANS, "ans");
applyMixin(Aptos, Coin, "coin");
applyMixin(Aptos, DigitalAsset, "digitalAsset");
applyMixin(Aptos, Event, "event");
applyMixin(Aptos, Experimental, "experimental");
applyMixin(Aptos, Faucet, "faucet");
applyMixin(Aptos, FungibleAsset, "fungibleAsset");
applyMixin(Aptos, General, "general");
Expand Down
4 changes: 2 additions & 2 deletions src/api/aptosConfig.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright © Aptos Foundation
// SPDX-License-Identifier: Apache-2.0

import aptosClient from "@aptos-labs/aptos-client";
import aptosClient, { bcsRequest } from "@aptos-labs/aptos-client";
import { AptosSettings, ClientConfig, Client, FullNodeConfig, IndexerConfig, FaucetConfig } from "../types";
import {
NetworkToNodeAPI,
Expand Down Expand Up @@ -140,7 +140,7 @@ export class AptosConfig {
this.pepper = settings?.pepper;
this.prover = settings?.prover;
this.indexer = settings?.indexer;
this.client = settings?.client ?? { provider: aptosClient };
this.client = settings?.client ?? { provider: aptosClient, binaryProvider: bcsRequest };
this.clientConfig = settings?.clientConfig ?? {};
this.fullnodeConfig = settings?.fullnodeConfig ?? {};
this.indexerConfig = settings?.indexerConfig ?? {};
Expand Down
64 changes: 64 additions & 0 deletions src/api/experimental.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// Copyright © Aptos Foundation
// SPDX-License-Identifier: Apache-2.0

import { LedgerVersionArg } from "../types";
import { AptosConfig } from "./aptosConfig";
import { InputViewFunctionData } from "../transactions";
import { viewBinary } from "../internal/experimental";

/**
* A class to have experimental functionality to the SDK. Anything used here is subject to change.
* @group Experimental
* @experimental
*/
export class Experimental {
/**
* Initializes a new instance of the Aptos client with the provided configuration.
*
* @param config - The configuration settings for the Aptos client.
* @param config.network - The network to connect to (e.g., Testnet, Mainnet).
* @param config.nodeUrl - The URL of the Aptos node to connect to.
* @param config.faucetUrl - The URL of the faucet to use for funding accounts.
*
* @example
* ```typescript
* import { Aptos, AptosConfig, Network } from "@aptos-labs/ts-sdk";
*
* async function runExample() {
* // Create a new Aptos client with Testnet configuration
* const config = new AptosConfig({ network: Network.TESTNET }); // Specify your own network if needed
* const aptos = new Aptos(config);
*
* console.log("Aptos client initialized:", aptos);
* }
* runExample().catch(console.error);
* ```
* @group Experimental
* @experimental
*/
constructor(readonly config: AptosConfig) {}

async viewBinary(args: {
payload: InputViewFunctionData;
options?: LedgerVersionArg & { convert?: undefined };
}): Promise<Uint8Array>;
async viewBinary<T extends {}>(args: {
payload: InputViewFunctionData;
options: LedgerVersionArg & { convert: (input: Uint8Array) => T };
}): Promise<T>;

/**
* Returns BCS encoded results of the view function. It can also convert the results to a specific type, if a
* converter is provided.
*
* @experimental
* @group Experimental
* @param args
*/
async viewBinary<T extends {} = Uint8Array>(args: {
payload: InputViewFunctionData;
options?: LedgerVersionArg & { convert?: (input: Uint8Array) => T };
}): Promise<Uint8Array | T> {
return viewBinary<T>({ ...args, aptosConfig: this.config });
}
}
Loading

0 comments on commit 4503a0a

Please sign in to comment.