Skip to content

Commit 4503a0a

Browse files
authored
[view] Add ability to get BCS output from view functions (#624)
NOTE: this is temporary, needs to be fixed to have a completely separate path in the SDK instead of the hack that is here.
1 parent cb4d657 commit 4503a0a

File tree

16 files changed

+586
-29
lines changed

16 files changed

+586
-29
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ All notable changes to the Aptos TypeScript SDK will be captured in this file. T
55
# Unreleased
66

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

912
# 1.34.0 (2025-02-06)
1013

examples/typescript/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@
2323
"local_node": "ts-node local_node.ts",
2424
"public_key_authenticator_account_abstraction": "ts-node public_key_authenticator_account_abstraction.ts",
2525
"hello_world_authenticator_account_abstraction": "ts-node hello_world_authenticator_account_abstraction.ts",
26-
"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"
26+
"view_bcs": "ts-node view_bcs.ts",
27+
"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"
2728
},
2829
"keywords": [],
2930
"author": "",

examples/typescript/view_bcs.ts

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
/* eslint-disable no-console */
2+
3+
/**
4+
* This example shows how to use the Aptos client to create accounts, fund them, and transfer between them.
5+
* Similar to ./simple_transfer.ts, but uses transferCoinTransaction to generate the transaction.
6+
*/
7+
8+
import {
9+
Account,
10+
AccountAddress,
11+
Aptos,
12+
AptosConfig,
13+
Deserializer,
14+
Network,
15+
NetworkToNetworkName,
16+
U64,
17+
} from "@aptos-labs/ts-sdk";
18+
19+
const ALICE_INITIAL_BALANCE = 100_000_000;
20+
const BOB_INITIAL_BALANCE = 0;
21+
const TRANSFER_AMOUNT = 1_000_000;
22+
23+
// Set up the client
24+
const APTOS_NETWORK: Network = NetworkToNetworkName[process.env.APTOS_NETWORK ?? Network.DEVNET];
25+
const config = new AptosConfig({ network: APTOS_NETWORK });
26+
const aptos = new Aptos(config);
27+
28+
/**
29+
* Prints the balance of an account
30+
* @param name
31+
* @param accountAddress
32+
* @returns {Promise<number>}
33+
*
34+
*/
35+
const balance = async (name: string, accountAddress: AccountAddress): Promise<number> => {
36+
const output = await aptos.experimental.viewBinary({
37+
payload: {
38+
function: "0x1::coin::balance",
39+
typeArguments: ["0x1::aptos_coin::AptosCoin"],
40+
functionArguments: [accountAddress],
41+
},
42+
});
43+
const deser = new Deserializer(output);
44+
const [wrappedAmount] = deser.deserializeVector(U64);
45+
const amount = Number(wrappedAmount.value);
46+
47+
console.log(`${name}'s balance is: ${amount}`);
48+
return amount;
49+
};
50+
51+
const example = async () => {
52+
console.log(
53+
"This example will create two accounts (Alice and Bob), fund Alice, and transfer between them using transferCoinTransaction.",
54+
);
55+
56+
// Create two accounts
57+
const alice = Account.generate();
58+
const bob = Account.generate();
59+
60+
console.log("=== Addresses ===\n");
61+
console.log(`Alice's address is: ${alice.accountAddress}`);
62+
console.log(`Bob's address is: ${bob.accountAddress}`);
63+
64+
// Fund the accounts
65+
console.log("\n=== Funding accounts ===\n");
66+
67+
// Fund alice account
68+
await aptos.fundAccount({
69+
accountAddress: alice.accountAddress,
70+
amount: ALICE_INITIAL_BALANCE,
71+
});
72+
73+
// Show the balances
74+
console.log("\n=== Initial Balances ===\n");
75+
const aliceBalance = await balance("Alice", alice.accountAddress);
76+
const bobBalance = await balance("Bob", bob.accountAddress);
77+
78+
if (aliceBalance !== ALICE_INITIAL_BALANCE) throw new Error("Alice's balance is incorrect");
79+
if (bobBalance !== BOB_INITIAL_BALANCE) throw new Error("Bob's balance is incorrect");
80+
81+
// Transfer between users
82+
console.log(`\n=== Transfer ${TRANSFER_AMOUNT} from Alice to Bob ===\n`);
83+
const transaction = await aptos.transferCoinTransaction({
84+
sender: alice.accountAddress,
85+
recipient: bob.accountAddress,
86+
amount: TRANSFER_AMOUNT,
87+
});
88+
const pendingTxn = await aptos.signAndSubmitTransaction({ signer: alice, transaction });
89+
const response = await aptos.waitForTransaction({ transactionHash: pendingTxn.hash });
90+
console.log(`Committed transaction: ${response.hash}`);
91+
92+
console.log("\n=== Balances after transfer ===\n");
93+
const newAliceBalance = await balance("Alice", alice.accountAddress);
94+
const newBobBalance = await balance("Bob", bob.accountAddress);
95+
96+
// Bob should have the transfer amount
97+
if (newBobBalance !== TRANSFER_AMOUNT + BOB_INITIAL_BALANCE)
98+
throw new Error("Bob's balance after transfer is incorrect");
99+
100+
// Alice should have the remainder minus gas
101+
if (newAliceBalance >= ALICE_INITIAL_BALANCE - TRANSFER_AMOUNT)
102+
throw new Error("Alice's balance after transfer is incorrect");
103+
};
104+
105+
example();

package.json

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@
5151
},
5252
"dependencies": {
5353
"@aptos-labs/aptos-cli": "^1.0.2",
54-
"@aptos-labs/aptos-client": "^0.1.1",
54+
"@aptos-labs/aptos-client": "^1.0.0",
5555
"@noble/curves": "^1.4.0",
5656
"@noble/hashes": "^1.4.0",
5757
"@scure/bip32": "^1.4.0",
@@ -97,10 +97,5 @@
9797
"typedoc-plugin-missing-exports": "^3.0.0",
9898
"typescript": "^5.6.2"
9999
},
100-
"pnpm": {
101-
"overrides": {
102-
"cross-spawn": ">=7.0.5"
103-
}
104-
},
105100
"version": "1.34.0"
106101
}

pnpm-lock.yaml

Lines changed: 10 additions & 12 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/api/aptos.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import { Table } from "./table";
1616
import { Keyless } from "./keyless";
1717
import { AptosObject } from "./object";
1818
import { AccountAbstraction } from "./account/abstraction";
19+
import { Experimental } from "./experimental";
1920

2021
/**
2122
* The main entry point for interacting with the Aptos APIs,
@@ -55,6 +56,8 @@ export class Aptos {
5556

5657
readonly event: Event;
5758

59+
readonly experimental: Experimental;
60+
5861
readonly faucet: Faucet;
5962

6063
readonly fungibleAsset: FungibleAsset;
@@ -100,6 +103,7 @@ export class Aptos {
100103
this.coin = new Coin(this.config);
101104
this.digitalAsset = new DigitalAsset(this.config);
102105
this.event = new Event(this.config);
106+
this.experimental = new Experimental(this.config);
103107
this.faucet = new Faucet(this.config);
104108
this.fungibleAsset = new FungibleAsset(this.config);
105109
this.general = new General(this.config);
@@ -119,6 +123,7 @@ export interface Aptos
119123
Coin,
120124
DigitalAsset,
121125
Event,
126+
Experimental,
122127
Faucet,
123128
FungibleAsset,
124129
General,
@@ -156,6 +161,7 @@ applyMixin(Aptos, ANS, "ans");
156161
applyMixin(Aptos, Coin, "coin");
157162
applyMixin(Aptos, DigitalAsset, "digitalAsset");
158163
applyMixin(Aptos, Event, "event");
164+
applyMixin(Aptos, Experimental, "experimental");
159165
applyMixin(Aptos, Faucet, "faucet");
160166
applyMixin(Aptos, FungibleAsset, "fungibleAsset");
161167
applyMixin(Aptos, General, "general");

src/api/aptosConfig.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// Copyright © Aptos Foundation
22
// SPDX-License-Identifier: Apache-2.0
33

4-
import aptosClient from "@aptos-labs/aptos-client";
4+
import aptosClient, { bcsRequest } from "@aptos-labs/aptos-client";
55
import { AptosSettings, ClientConfig, Client, FullNodeConfig, IndexerConfig, FaucetConfig } from "../types";
66
import {
77
NetworkToNodeAPI,
@@ -140,7 +140,7 @@ export class AptosConfig {
140140
this.pepper = settings?.pepper;
141141
this.prover = settings?.prover;
142142
this.indexer = settings?.indexer;
143-
this.client = settings?.client ?? { provider: aptosClient };
143+
this.client = settings?.client ?? { provider: aptosClient, binaryProvider: bcsRequest };
144144
this.clientConfig = settings?.clientConfig ?? {};
145145
this.fullnodeConfig = settings?.fullnodeConfig ?? {};
146146
this.indexerConfig = settings?.indexerConfig ?? {};

src/api/experimental.ts

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
// Copyright © Aptos Foundation
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
import { LedgerVersionArg } from "../types";
5+
import { AptosConfig } from "./aptosConfig";
6+
import { InputViewFunctionData } from "../transactions";
7+
import { viewBinary } from "../internal/experimental";
8+
9+
/**
10+
* A class to have experimental functionality to the SDK. Anything used here is subject to change.
11+
* @group Experimental
12+
* @experimental
13+
*/
14+
export class Experimental {
15+
/**
16+
* Initializes a new instance of the Aptos client with the provided configuration.
17+
*
18+
* @param config - The configuration settings for the Aptos client.
19+
* @param config.network - The network to connect to (e.g., Testnet, Mainnet).
20+
* @param config.nodeUrl - The URL of the Aptos node to connect to.
21+
* @param config.faucetUrl - The URL of the faucet to use for funding accounts.
22+
*
23+
* @example
24+
* ```typescript
25+
* import { Aptos, AptosConfig, Network } from "@aptos-labs/ts-sdk";
26+
*
27+
* async function runExample() {
28+
* // Create a new Aptos client with Testnet configuration
29+
* const config = new AptosConfig({ network: Network.TESTNET }); // Specify your own network if needed
30+
* const aptos = new Aptos(config);
31+
*
32+
* console.log("Aptos client initialized:", aptos);
33+
* }
34+
* runExample().catch(console.error);
35+
* ```
36+
* @group Experimental
37+
* @experimental
38+
*/
39+
constructor(readonly config: AptosConfig) {}
40+
41+
async viewBinary(args: {
42+
payload: InputViewFunctionData;
43+
options?: LedgerVersionArg & { convert?: undefined };
44+
}): Promise<Uint8Array>;
45+
async viewBinary<T extends {}>(args: {
46+
payload: InputViewFunctionData;
47+
options: LedgerVersionArg & { convert: (input: Uint8Array) => T };
48+
}): Promise<T>;
49+
50+
/**
51+
* Returns BCS encoded results of the view function. It can also convert the results to a specific type, if a
52+
* converter is provided.
53+
*
54+
* @experimental
55+
* @group Experimental
56+
* @param args
57+
*/
58+
async viewBinary<T extends {} = Uint8Array>(args: {
59+
payload: InputViewFunctionData;
60+
options?: LedgerVersionArg & { convert?: (input: Uint8Array) => T };
61+
}): Promise<Uint8Array | T> {
62+
return viewBinary<T>({ ...args, aptosConfig: this.config });
63+
}
64+
}

0 commit comments

Comments
 (0)